From c76957e503bcc7a2b75255c44e5b4e6208315421 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:31:21 +0000 Subject: [PATCH 1/3] Extract libunwind from llvm 22.1.0 archive --- .../external/llvm-libunwind/CMakeLists.txt | 10 + .../llvm-libunwind/cmake/config-ix.cmake | 56 -- .../llvm-libunwind/docs/BuildingLibunwind.rst | 2 +- .../llvm-libunwind/include/CMakeLists.txt | 6 +- .../include/__libunwind_config.h | 34 +- .../llvm-libunwind/include/libunwind.h | 152 ++++- .../llvm-libunwind/include/unwind_arm_ehabi.h | 13 +- .../llvm-libunwind/include/unwind_itanium.h | 2 +- .../llvm-libunwind/src/AddressSpace.hpp | 66 +- .../llvm-libunwind/src/CMakeLists.txt | 96 +-- .../llvm-libunwind/src/CompactUnwinder.hpp | 245 ++++---- .../llvm-libunwind/src/DwarfInstructions.hpp | 89 ++- .../llvm-libunwind/src/DwarfParser.hpp | 82 ++- .../llvm-libunwind/src/EHHeaderParser.hpp | 11 +- .../external/llvm-libunwind/src/Registers.hpp | 594 ++++++++---------- .../llvm-libunwind/src/Unwind-EHABI.cpp | 32 +- .../llvm-libunwind/src/Unwind-seh.cpp | 57 +- .../external/llvm-libunwind/src/Unwind-wasm.c | 20 +- .../llvm-libunwind/src/UnwindCursor.hpp | 545 +++++++++++----- .../llvm-libunwind/src/UnwindLevel1.c | 132 ++-- .../src/UnwindRegistersRestore.S | 60 +- .../llvm-libunwind/src/UnwindRegistersSave.S | 137 +++- .../llvm-libunwind/src/Unwind_AIXExtras.cpp | 1 + .../external/llvm-libunwind/src/assembly.h | 6 +- .../external/llvm-libunwind/src/config.h | 9 + .../external/llvm-libunwind/src/libunwind.cpp | 125 +++- .../llvm-libunwind/src/libunwind_ext.h | 11 +- .../{cet_unwind.h => shadow_stack_unwind.h} | 16 +- .../llvm-libunwind/test/CMakeLists.txt | 29 +- .../test/aarch64_vg_unwind.pass.cpp | 69 ++ .../test/aarch64_za_unwind.pass.cpp | 118 ++++ .../test/aix_signal_unwind.pass.sh.S | 7 +- .../test/bad_unwind_info.pass.cpp | 9 +- .../configs/apple-libunwind-system.cfg.in | 2 +- .../configs/armv7m-picolibc-libunwind.cfg.in | 4 +- .../test/configs/cmake-bridge.cfg.in | 11 + .../test/configs/ibm-libunwind-shared.cfg.in | 2 +- .../test/configs/llvm-libunwind-merged.cfg.in | 2 +- .../llvm-libunwind-shared-mingw.cfg.in | 2 +- .../test/configs/llvm-libunwind-shared.cfg.in | 2 +- .../llvm-libunwind-static-mingw.cfg.in | 2 +- .../test/configs/llvm-libunwind-static.cfg.in | 2 +- .../test/eh_frame_fde_pc_range.pass.cpp | 61 ++ .../test/floatregister.pass.cpp | 5 +- .../llvm-libunwind/test/forceunwind.pass.cpp | 6 +- .../test/remember_state_leak.pass.sh.s | 5 +- .../test/signal_unwind.pass.cpp | 4 +- .../llvm-libunwind/test/unw_resume.pass.cpp | 2 +- .../test/unwind_leaffunction.pass.cpp | 4 +- .../test/unwind_scalable_vectors.pass.cpp | 9 +- 50 files changed, 1947 insertions(+), 1019 deletions(-) rename src/native/external/llvm-libunwind/src/{cet_unwind.h => shadow_stack_unwind.h} (83%) create mode 100644 src/native/external/llvm-libunwind/test/aarch64_vg_unwind.pass.cpp create mode 100644 src/native/external/llvm-libunwind/test/aarch64_za_unwind.pass.cpp create mode 100644 src/native/external/llvm-libunwind/test/eh_frame_fde_pc_range.pass.cpp diff --git a/src/native/external/llvm-libunwind/CMakeLists.txt b/src/native/external/llvm-libunwind/CMakeLists.txt index 3c8499fd334649..fbef71f3f74467 100644 --- a/src/native/external/llvm-libunwind/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/CMakeLists.txt @@ -145,6 +145,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) if(LIBUNWIND_LIBDIR_SUBDIR) string(APPEND LIBUNWIND_TARGET_SUBDIR /${LIBUNWIND_LIBDIR_SUBDIR}) endif() + cmake_path(NORMAL_PATH LIBUNWIND_TARGET_SUBDIR) set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LIBUNWIND_TARGET_SUBDIR}) set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBUNWIND_TARGET_SUBDIR} CACHE STRING "Path where built libunwind libraries should be installed.") @@ -181,6 +182,8 @@ include(HandleLibunwindFlags) # Configure compiler. include(config-ix) +include(HandleLibC) # Setup the C library flags + if (LIBUNWIND_USE_COMPILER_RT AND NOT LIBUNWIND_HAS_NODEFAULTLIBS_FLAG) list(APPEND LIBUNWIND_LINK_FLAGS "-rtlib=compiler-rt") endif() @@ -329,6 +332,13 @@ if (C_SUPPORTS_COMMENT_LIB_PRAGMA) endif() endif() +if (RUNTIMES_EXECUTE_ONLY_CODE) + add_compile_definitions(_LIBUNWIND_EXECUTE_ONLY_CODE) +endif() + +add_custom_target(unwind-test-depends + COMMENT "Build dependencies required to run the libunwind test suite.") + #=============================================================================== # Setup Source Code #=============================================================================== diff --git a/src/native/external/llvm-libunwind/cmake/config-ix.cmake b/src/native/external/llvm-libunwind/cmake/config-ix.cmake index 126c872f0d4895..d42ceffb1f631e 100644 --- a/src/native/external/llvm-libunwind/cmake/config-ix.cmake +++ b/src/native/external/llvm-libunwind/cmake/config-ix.cmake @@ -26,62 +26,6 @@ if (NOT LIBUNWIND_USE_COMPILER_RT) endif () endif() -# libunwind is using -nostdlib++ at the link step when available, -# otherwise -nodefaultlibs is used. We want all our checks to also -# use one of these options, otherwise we may end up with an inconsistency between -# the flags we think we require during configuration (if the checks are -# performed without one of those options) and the flags that are actually -# required during compilation (which has the -nostdlib++ or -nodefaultlibs). libc is -# required for the link to go through. We remove sanitizers from the -# configuration checks to avoid spurious link errors. - -llvm_check_compiler_linker_flag(CXX "-nostdlib++" CXX_SUPPORTS_NOSTDLIBXX_FLAG) -if (CXX_SUPPORTS_NOSTDLIBXX_FLAG) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nostdlib++") -else() - llvm_check_compiler_linker_flag(C "-nodefaultlibs" C_SUPPORTS_NODEFAULTLIBS_FLAG) - if (C_SUPPORTS_NODEFAULTLIBS_FLAG) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs") - endif() -endif() - -# Only link against compiler-rt manually if we use -nodefaultlibs, since -# otherwise the compiler will do the right thing on its own. -if (NOT CXX_SUPPORTS_NOSTDLIBXX_FLAG AND C_SUPPORTS_NODEFAULTLIBS_FLAG) - if (LIBUNWIND_HAS_C_LIB) - list(APPEND CMAKE_REQUIRED_LIBRARIES c) - endif () - if (LIBUNWIND_HAS_ROOT_LIB) - list(APPEND CMAKE_REQUIRED_LIBRARIES root) - endif () - if (LIBUNWIND_USE_COMPILER_RT) - include(HandleCompilerRT) - find_compiler_rt_library(builtins LIBUNWIND_BUILTINS_LIBRARY - FLAGS ${LIBUNWIND_COMPILE_FLAGS}) - list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBUNWIND_BUILTINS_LIBRARY}") - else () - if (LIBUNWIND_HAS_GCC_S_LIB) - list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s) - endif () - if (LIBUNWIND_HAS_GCC_LIB) - list(APPEND CMAKE_REQUIRED_LIBRARIES gcc) - endif () - endif () - if (MINGW) - # Mingw64 requires quite a few "C" runtime libraries in order for basic - # programs to link successfully with -nodefaultlibs. - if (LIBUNWIND_USE_COMPILER_RT) - set(MINGW_RUNTIME ${LIBUNWIND_BUILTINS_LIBRARY}) - else () - set(MINGW_RUNTIME gcc_s gcc) - endif() - set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32 - shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME} - moldname mingwex msvcrt) - list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES}) - endif() -endif() - if (CXX_SUPPORTS_NOSTDLIBXX_FLAG OR C_SUPPORTS_NODEFAULTLIBS_FLAG) if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") diff --git a/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst b/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst index 8b4f1207d4ba99..c231587fd50224 100644 --- a/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst +++ b/src/native/external/llvm-libunwind/docs/BuildingLibunwind.rst @@ -91,7 +91,7 @@ libunwind specific options .. option:: LIBUNWIND_ENABLE_WERROR:BOOL - **Default**: ``ON`` + **Default**: ``OFF`` Compile with -Werror diff --git a/src/native/external/llvm-libunwind/include/CMakeLists.txt b/src/native/external/llvm-libunwind/include/CMakeLists.txt index 6796d67a3354ff..eefd4305d06cc1 100644 --- a/src/native/external/llvm-libunwind/include/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/include/CMakeLists.txt @@ -21,12 +21,10 @@ if(LIBUNWIND_INSTALL_HEADERS) ) endforeach() - if(NOT CMAKE_CONFIGURATION_TYPES) + if (NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-unwind-headers DEPENDS unwind-headers - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=unwind-headers - -P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake") + COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" --component unwind-headers) add_custom_target(install-unwind-headers-stripped DEPENDS install-unwind-headers) endif() endif() diff --git a/src/native/external/llvm-libunwind/include/__libunwind_config.h b/src/native/external/llvm-libunwind/include/__libunwind_config.h index ec56ded7e2882f..980d11ef5d4f23 100644 --- a/src/native/external/llvm-libunwind/include/__libunwind_config.h +++ b/src/native/external/llvm-libunwind/include/__libunwind_config.h @@ -41,8 +41,8 @@ # endif # if defined(__i386__) # define _LIBUNWIND_TARGET_I386 -# define _LIBUNWIND_CONTEXT_SIZE 13 -# define _LIBUNWIND_CURSOR_SIZE 20 +# define _LIBUNWIND_CONTEXT_SIZE 8 +# define _LIBUNWIND_CURSOR_SIZE 15 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 # elif defined(__x86_64__) # define _LIBUNWIND_TARGET_X86_64 1 @@ -57,8 +57,8 @@ # define _LIBUNWIND_CONTEXT_SIZE 21 # define _LIBUNWIND_CURSOR_SIZE 28 # else -# define _LIBUNWIND_CONTEXT_SIZE 38 -# define _LIBUNWIND_CURSOR_SIZE 50 +# define _LIBUNWIND_CONTEXT_SIZE 21 +# define _LIBUNWIND_CURSOR_SIZE 33 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 # elif defined(__powerpc64__) @@ -73,11 +73,11 @@ # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC # elif defined(__aarch64__) # define _LIBUNWIND_TARGET_AARCH64 1 -# define _LIBUNWIND_CONTEXT_SIZE 100 +#define _LIBUNWIND_CONTEXT_SIZE 67 # if defined(__SEH__) -# define _LIBUNWIND_CURSOR_SIZE 198 +# define _LIBUNWIND_CURSOR_SIZE 164 # else -# define _LIBUNWIND_CURSOR_SIZE 112 +#define _LIBUNWIND_CURSOR_SIZE 79 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 # elif defined(__arm__) @@ -89,8 +89,8 @@ # define _LIBUNWIND_CONTEXT_SIZE 61 # define _LIBUNWIND_CURSOR_SIZE 68 # else -# define _LIBUNWIND_CONTEXT_SIZE 50 -# define _LIBUNWIND_CURSOR_SIZE 57 +# define _LIBUNWIND_CONTEXT_SIZE 42 +# define _LIBUNWIND_CURSOR_SIZE 49 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM # elif defined(__or1k__) @@ -154,7 +154,7 @@ # else # define RISCV_FLEN 0 # endif -# define _LIBUNWIND_CONTEXT_SIZE (32 * (__riscv_xlen + RISCV_FLEN) / 64) + 32 +# define _LIBUNWIND_CONTEXT_SIZE (32 * (__riscv_xlen + RISCV_FLEN) / 64) # if __riscv_xlen == 32 # define _LIBUNWIND_CURSOR_SIZE (_LIBUNWIND_CONTEXT_SIZE + 7) # elif __riscv_xlen == 64 @@ -176,15 +176,14 @@ #elif defined(__loongarch__) #define _LIBUNWIND_TARGET_LOONGARCH 1 #if __loongarch_grlen == 64 -#define _LIBUNWIND_CONTEXT_SIZE 98 -#define _LIBUNWIND_CURSOR_SIZE 110 +#define _LIBUNWIND_CONTEXT_SIZE 65 +#define _LIBUNWIND_CURSOR_SIZE 77 #else #error "Unsupported LoongArch ABI" #endif #define _LIBUNWIND_HIGHEST_DWARF_REGISTER \ _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH #elif defined(__wasm__) -#define _LIBUNWIND_TARGET_WASM 1 // Unused #define _LIBUNWIND_CONTEXT_SIZE 0 #define _LIBUNWIND_CURSOR_SIZE 0 @@ -213,4 +212,13 @@ # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 #endif // _LIBUNWIND_IS_NATIVE_ONLY +#if defined(__has_feature) +# if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns) +# define _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING 1 +# elif __has_feature(ptrauth_calls) != __has_feature(ptrauth_returns) +# error "Either both or none of ptrauth_calls and ptrauth_returns "\ + "is allowed to be enabled" +# endif +#endif + #endif // ____LIBUNWIND_CONFIG_H__ diff --git a/src/native/external/llvm-libunwind/include/libunwind.h b/src/native/external/llvm-libunwind/include/libunwind.h index 7a8fcbcb26745a..56ca7110274a30 100644 --- a/src/native/external/llvm-libunwind/include/libunwind.h +++ b/src/native/external/llvm-libunwind/include/libunwind.h @@ -43,6 +43,109 @@ #define LIBUNWIND_AVAIL #endif +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + + #include + + // `__ptrauth_restricted_intptr` is a feature of apple clang that predates + // support for direct application of `__ptrauth` to integer types. This + // guard is necessary to support compilation with those compiler. + #if __has_extension(ptrauth_restricted_intptr_qualifier) + #define __unwind_ptrauth_restricted_intptr(...) \ + __ptrauth_restricted_intptr(__VA_ARGS__) + #else + #define __unwind_ptrauth_restricted_intptr(...) \ + __ptrauth(__VA_ARGS__) + #endif + + // ptrauth_string_discriminator("unw_proc_info_t::handler") == 0x7405 + #define __ptrauth_unwind_upi_handler_disc 0x7405 + + #define __ptrauth_unwind_upi_handler \ + __ptrauth(ptrauth_key_function_pointer, 1, __ptrauth_unwind_upi_handler_disc) + + #define __ptrauth_unwind_upi_handler_intptr \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1,\ + __ptrauth_unwind_upi_handler_disc) + + // ptrauth_string_discriminator("unw_proc_info_t::start_ip") == 0xCA2C + #define __ptrauth_unwind_upi_startip \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xCA2C) + + // ptrauth_string_discriminator("unw_proc_info_t::end_ip") == 0xE183 + #define __ptrauth_unwind_upi_endip \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xE183) + + // ptrauth_string_discriminator("unw_proc_info_t::lsda") == 0x83DE + #define __ptrauth_unwind_upi_lsda \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x83DE) + + // ptrauth_string_discriminator("unw_proc_info_t::flags") == 0x79A1 + #define __ptrauth_unwind_upi_flags \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x79A1) + + // ptrauth_string_discriminator("unw_proc_info_t::unwind_info") == 0xC20C + #define __ptrauth_unwind_upi_info \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xC20C) + + // ptrauth_string_discriminator("unw_proc_info_t::extra") == 0x03DF + #define __ptrauth_unwind_upi_extra \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x03DF) + + // ptrauth_string_discriminator("Registers_arm64::link_reg_t") == 0x8301 + #define __ptrauth_unwind_registers_arm64_link_reg \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_code, 1, 0x8301) + + // ptrauth_string_discriminator("UnwindInfoSections::dso_base") == 0x4FF5 + #define __ptrauth_unwind_uis_dso_base \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4FF5) + + // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section") == 0x4974 + #define __ptrauth_unwind_uis_dwarf_section \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4974) + + // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section_length") == 0x2A9A + #define __ptrauth_unwind_uis_dwarf_section_length \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x2A9A) + + // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section") == 0xA27B + #define __ptrauth_unwind_uis_compact_unwind_section \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xA27B) + + // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section_length") == 0x5D0A + #define __ptrauth_unwind_uis_compact_unwind_section_length \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x5D0A) + + // ptrauth_string_discriminator("CIE_Info::personality") == 0x6A40 + #define __ptrauth_unwind_cie_info_personality_disc 0x6A40 + #define __ptrauth_unwind_cie_info_personality \ + __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \ + __ptrauth_unwind_cie_info_personality_disc) + + // ptrauth_string_discriminator("personality") == 0x7EAD) + #define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD + +#else + + #define __unwind_ptrauth_restricted_intptr(...) + #define __ptrauth_unwind_upi_handler + #define __ptrauth_unwind_upi_handler_intptr + #define __ptrauth_unwind_upi_startip + #define __ptrauth_unwind_upi_endip + #define __ptrauth_unwind_upi_lsda + #define __ptrauth_unwind_upi_flags + #define __ptrauth_unwind_upi_info + #define __ptrauth_unwind_upi_extra + #define __ptrauth_unwind_registers_arm64_link_reg + #define __ptrauth_unwind_uis_dso_base + #define __ptrauth_unwind_uis_dwarf_section + #define __ptrauth_unwind_uis_dwarf_section_length + #define __ptrauth_unwind_uis_compact_unwind_section + #define __ptrauth_unwind_uis_compact_unwind_section_length + #define __ptrauth_unwind_cie_info_personality + +#endif + #if defined(_WIN32) && defined(__SEH__) #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16))) #else @@ -88,39 +191,20 @@ typedef double unw_fpreg_t; #endif struct unw_proc_info_t { - unw_word_t start_ip; /* start address of function */ - unw_word_t end_ip; /* address after end of function */ - unw_word_t lsda; /* address of language specific data area, */ - /* or zero if not used */ - unw_word_t handler; /* personality routine, or zero if not used */ - 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 */ - unw_word_t extra; /* mach_header of mach-o image containing func */ -}; -typedef struct unw_proc_info_t unw_proc_info_t; + unw_word_t __ptrauth_unwind_upi_startip start_ip; /* start address of function */ + unw_word_t __ptrauth_unwind_upi_endip end_ip; /* address after end of function */ + unw_word_t __ptrauth_unwind_upi_lsda lsda; /* address of language specific data area, */ + /* or zero if not used */ -enum unw_save_loc_type_t -{ - UNW_SLT_NONE, /* register is not saved ("not an l-value") */ - UNW_SLT_MEMORY, /* register has been saved in memory */ - UNW_SLT_REG /* register has been saved in (another) register */ -}; -typedef enum unw_save_loc_type_t unw_save_loc_type_t; - -struct unw_save_loc_t -{ - unw_save_loc_type_t type; - union - { - unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ - unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ - } - u; + unw_word_t __ptrauth_unwind_upi_handler_intptr handler; + unw_word_t gp; /* not used */ + unw_word_t __ptrauth_unwind_upi_flags 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 __ptrauth_unwind_upi_info unwind_info; /* address of DWARF unwind info, or zero */ + unw_word_t __ptrauth_unwind_upi_extra extra; /* mach_header of mach-o image containing func */ }; -typedef struct unw_save_loc_t unw_save_loc_t; +typedef struct unw_proc_info_t unw_proc_info_t; #ifdef __cplusplus extern "C" { @@ -131,7 +215,7 @@ extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; -extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *) LIBUNWIND_AVAIL; +extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; @@ -149,7 +233,8 @@ extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; -extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*) LIBUNWIND_AVAIL; +//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); +extern const char *unw_strerror(int) LIBUNWIND_AVAIL; extern unw_addr_space_t unw_local_addr_space; @@ -552,6 +637,7 @@ enum { UNW_AARCH64_X31 = 31, UNW_AARCH64_SP = 31, UNW_AARCH64_PC = 32, + UNW_AARCH64_VG = 46, // reserved block UNW_AARCH64_RA_SIGN_STATE = 34, diff --git a/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h b/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h index 5fa94a167ff100..68e02e47602d60 100644 --- a/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h +++ b/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h @@ -118,15 +118,18 @@ _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, extern _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep, uintptr_t *pos); + void *valuep); extern _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t discriminator, _Unwind_VRS_DataRepresentation representation); +extern _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *, + _Unwind_Context *); + #if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) -#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern +#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern __inline__ #else #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ #endif @@ -147,8 +150,8 @@ uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value, uintptr_t *pos) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value, pos); + uintptr_t value) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); } _LIBUNWIND_EXPORT_UNWIND_LEVEL1 @@ -160,7 +163,7 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, value | thumb_bit, NULL); + _Unwind_SetGR(context, 15, value | thumb_bit); } #ifdef __cplusplus diff --git a/src/native/external/llvm-libunwind/include/unwind_itanium.h b/src/native/external/llvm-libunwind/include/unwind_itanium.h index 7e813c7c2b07a0..d94a6183be2901 100644 --- a/src/native/external/llvm-libunwind/include/unwind_itanium.h +++ b/src/native/external/llvm-libunwind/include/unwind_itanium.h @@ -65,7 +65,7 @@ extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value, uintptr_t *pos); + uintptr_t new_value); extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); diff --git a/src/native/external/llvm-libunwind/src/AddressSpace.hpp b/src/native/external/llvm-libunwind/src/AddressSpace.hpp index 33f64415298264..52477b16b355aa 100644 --- a/src/native/external/llvm-libunwind/src/AddressSpace.hpp +++ b/src/native/external/llvm-libunwind/src/AddressSpace.hpp @@ -22,7 +22,6 @@ #include "dwarf2.h" #include "EHHeaderParser.hpp" #include "Registers.hpp" -#include "libunwind_ext.h" #ifndef _LIBUNWIND_USE_DLADDR #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX)) @@ -130,22 +129,27 @@ struct UnwindInfoSections { defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) // No dso_base for SEH. - uintptr_t dso_base; + uintptr_t __ptrauth_unwind_uis_dso_base + dso_base = 0; #endif #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) size_t text_segment_length; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - uintptr_t dwarf_section; - size_t dwarf_section_length; + uintptr_t __ptrauth_unwind_uis_dwarf_section + dwarf_section = 0; + size_t __ptrauth_unwind_uis_dwarf_section_length + dwarf_section_length = 0; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) uintptr_t dwarf_index_section; size_t dwarf_index_section_length; #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - uintptr_t compact_unwind_section; - size_t compact_unwind_section_length; + uintptr_t __ptrauth_unwind_uis_compact_unwind_section + compact_unwind_section = 0; + size_t __ptrauth_unwind_uis_compact_unwind_section_length + compact_unwind_section_length = 0; #endif #if defined(_LIBUNWIND_ARM_EHABI) uintptr_t arm_section; @@ -197,11 +201,16 @@ class _LIBUNWIND_HIDDEN LocalAddressSpace { static int64_t getSLEB128(pint_t &addr, pint_t end); pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, - pint_t datarelBase = 0); - bool findFunctionName(pint_t addr, char *buf, size_t bufLen, - unw_word_t *offset); - bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); - bool findOtherFDE(pint_t targetAddr, pint_t &fde); + pint_t datarelBase = 0, pint_t *resultAddr = nullptr); + template + bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf, + size_t bufLen, unw_word_t *offset); + template + bool findUnwindSections(typename R::link_hardened_reg_arg_t targetAddr, + UnwindInfoSections &info); + template + bool findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, + pint_t &fde); static LocalAddressSpace sThisAddressSpace; }; @@ -270,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, - pint_t datarelBase) { + pint_t datarelBase, pint_t *resultAddr) { pint_t startAddr = addr; const uint8_t *p = (uint8_t *)addr; pint_t result; @@ -354,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, break; } - if (encoding & DW_EH_PE_indirect) + if (encoding & DW_EH_PE_indirect) { + if (resultAddr) + *resultAddr = result; result = getP(result); + } else { + if (resultAddr) + *resultAddr = startAddr; + } return result; } @@ -487,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - -inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, - UnwindInfoSections &info) { +template +inline bool LocalAddressSpace::findUnwindSections( + typename R::link_hardened_reg_arg_t targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { @@ -604,7 +619,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind // support for _dl_find_object on other unwind formats is not implemented, // yet. -#if defined(DLFO_STRUCT_HAS_EH_DBASE) && defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) && DLFO_EH_SEGMENT_TYPE == PT_GNU_EH_FRAME +#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. +#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME +#error _dl_find_object retrieves an unexpected section type +#endif // We look-up `dl_find_object` dynamically at runtime to ensure backwards // compatibility with earlier version of glibc not yet providing it. On older // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer @@ -655,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, return false; } -inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { +template +inline bool +LocalAddressSpace::findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, + pint_t &fde) { // TO DO: if OS has way to dynamically register FDEs, check that. (void)targetAddr; (void)fde; return false; } -inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, - size_t bufLen, - unw_word_t *offset) { +template +inline bool +LocalAddressSpace::findFunctionName(typename R::link_hardened_reg_arg_t addr, + char *buf, size_t bufLen, + unw_word_t *offset) { #if _LIBUNWIND_USE_DLADDR Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { diff --git a/src/native/external/llvm-libunwind/src/CMakeLists.txt b/src/native/external/llvm-libunwind/src/CMakeLists.txt index ecbd019bb29ea8..6e947039fb0d52 100644 --- a/src/native/external/llvm-libunwind/src/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/src/CMakeLists.txt @@ -6,7 +6,7 @@ set(LIBUNWIND_CXX_SOURCES Unwind-seh.cpp ) -if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") +if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX") list(APPEND LIBUNWIND_CXX_SOURCES Unwind_AIXExtras.cpp ) @@ -36,7 +36,6 @@ set(LIBUNWIND_HEADERS AddressSpace.hpp assembly.h CompactUnwinder.hpp - cet_unwind.h config.h dwarf2.h DwarfInstructions.hpp @@ -46,6 +45,7 @@ set(LIBUNWIND_HEADERS libunwind_ext.h Registers.hpp RWMutex.hpp + shadow_stack_unwind.h Unwind-EHABI.h UnwindCursor.hpp ../include/libunwind.h @@ -71,18 +71,6 @@ set(LIBUNWIND_SOURCES ${LIBUNWIND_ASM_SOURCES}) # Generate library list. -if (CXX_SUPPORTS_NOSTDLIBXX_FLAG) - add_link_flags_if_supported(-nostdlib++) -else() - if (LIBUNWIND_USE_COMPILER_RT) - add_library_flags("${LIBUNWIND_BUILTINS_LIBRARY}") - else() - add_library_flags_if(LIBUNWIND_HAS_GCC_S_LIB gcc_s) - add_library_flags_if(LIBUNWIND_HAS_GCC_LIB gcc) - endif() - add_library_flags_if(LIBUNWIND_HAS_C_LIB c) -endif() - if (NOT APPLE) add_library_flags_if(LIBUNWIND_HAS_DL_LIB dl) endif() @@ -118,22 +106,6 @@ if (HAIKU) add_compile_flags("-D_DEFAULT_SOURCE") add_compile_flags("-DPT_GNU_EH_FRAME=PT_EH_FRAME") - - find_path(LIBUNWIND_HAIKU_PRIVATE_HEADERS - "commpage_defs.h" - PATHS ${CMAKE_SYSTEM_INCLUDE_PATH} - PATH_SUFFIXES "/private/system" - NO_DEFAULT_PATH - REQUIRED) - - include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}") - if (LIBUNWIND_TARGET_TRIPLE) - if (${LIBUNWIND_TARGET_TRIPLE} MATCHES "^x86_64") - include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/x86_64") - endif() - else() - include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/${CMAKE_SYSTEM_PROCESSOR}") - endif() endif () string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}") @@ -160,9 +132,10 @@ if(CMAKE_C_COMPILER_ID STREQUAL MSVC) else() target_compile_options(unwind_shared_objects PRIVATE -fno-rtti) endif() -target_link_libraries(unwind_shared_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES}) target_compile_options(unwind_shared_objects PUBLIC "${LIBUNWIND_ADDITIONAL_COMPILE_FLAGS}") -target_link_libraries(unwind_shared_objects PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}") +target_link_libraries(unwind_shared_objects + PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}" + PRIVATE unwind-headers runtimes-libc-headers ${LIBUNWIND_LIBRARIES}) set_target_properties(unwind_shared_objects PROPERTIES CXX_EXTENSIONS OFF @@ -175,7 +148,7 @@ if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CO endif() add_library(unwind_shared SHARED) -target_link_libraries(unwind_shared PUBLIC unwind_shared_objects) +target_link_libraries(unwind_shared PUBLIC unwind_shared_objects runtimes-libc-shared) set_target_properties(unwind_shared PROPERTIES EXCLUDE_FROM_ALL "$,FALSE,TRUE>" @@ -186,13 +159,6 @@ set_target_properties(unwind_shared SOVERSION "1" ) -if (LIBUNWIND_ENABLE_SHARED) - list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_shared") -endif() -if (LIBUNWIND_INSTALL_SHARED_LIBRARY) - list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_shared") -endif() - # Build the static library. add_library(unwind_static_objects OBJECT EXCLUDE_FROM_ALL ${LIBUNWIND_SOURCES} ${LIBUNWIND_HEADERS}) cxx_add_warning_flags(unwind_static_objects ${LIBUNWIND_ENABLE_WERROR} ${LIBUNWIND_ENABLE_PEDANTIC}) @@ -201,9 +167,10 @@ if(CMAKE_C_COMPILER_ID STREQUAL MSVC) else() target_compile_options(unwind_static_objects PRIVATE -fno-rtti) endif() -target_link_libraries(unwind_static_objects PRIVATE unwind-headers ${LIBUNWIND_LIBRARIES}) target_compile_options(unwind_static_objects PUBLIC "${LIBUNWIND_ADDITIONAL_COMPILE_FLAGS}") -target_link_libraries(unwind_static_objects PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}") +target_link_libraries(unwind_static_objects + PUBLIC "${LIBUNWIND_ADDITIONAL_LIBRARIES}" + PRIVATE unwind-headers runtimes-libc-headers ${LIBUNWIND_LIBRARIES}) set_target_properties(unwind_static_objects PROPERTIES CXX_EXTENSIONS OFF @@ -222,7 +189,7 @@ if(LIBUNWIND_HIDE_SYMBOLS) endif() add_library(unwind_static STATIC) -target_link_libraries(unwind_static PUBLIC unwind_static_objects) +target_link_libraries(unwind_static PUBLIC unwind_static_objects runtimes-libc-static) set_target_properties(unwind_static PROPERTIES EXCLUDE_FROM_ALL "$,FALSE,TRUE>" @@ -231,35 +198,40 @@ set_target_properties(unwind_static OUTPUT_NAME "${LIBUNWIND_STATIC_OUTPUT_NAME}" ) -if (LIBUNWIND_ENABLE_STATIC) - list(APPEND LIBUNWIND_BUILD_TARGETS "unwind_static") +# Add a meta-target for both libraries. +add_custom_target(unwind) +if (LIBUNWIND_ENABLE_SHARED) + add_dependencies(unwind unwind_shared) endif() -if (LIBUNWIND_INSTALL_STATIC_LIBRARY) - list(APPEND LIBUNWIND_INSTALL_TARGETS "unwind_static") +if (LIBUNWIND_ENABLE_STATIC) + add_dependencies(unwind unwind_static) endif() -# Add a meta-target for both libraries. -add_custom_target(unwind DEPENDS ${LIBUNWIND_BUILD_TARGETS}) - -if (LIBUNWIND_INSTALL_LIBRARY) - install(TARGETS ${LIBUNWIND_INSTALL_TARGETS} +if (LIBUNWIND_INSTALL_SHARED_LIBRARY) + install(TARGETS unwind_shared + ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind LIBRARY DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind + RUNTIME DESTINATION ${LIBUNWIND_INSTALL_RUNTIME_DIR} COMPONENT unwind) +endif() + +if (LIBUNWIND_INSTALL_STATIC_LIBRARY) + install(TARGETS unwind_static ARCHIVE DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind + LIBRARY DESTINATION ${LIBUNWIND_INSTALL_LIBRARY_DIR} COMPONENT unwind RUNTIME DESTINATION ${LIBUNWIND_INSTALL_RUNTIME_DIR} COMPONENT unwind) endif() -if (NOT CMAKE_CONFIGURATION_TYPES AND LIBUNWIND_INSTALL_LIBRARY) +if (NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-unwind - DEPENDS unwind - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=unwind - -P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake") + COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" --component unwind) add_custom_target(install-unwind-stripped - DEPENDS unwind - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=unwind - -DCMAKE_INSTALL_DO_STRIP=1 - -P "${LIBUNWIND_BINARY_DIR}/cmake_install.cmake") + COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" --component unwind --strip) + + if (LIBUNWIND_INSTALL_LIBRARY) + add_dependencies(install-unwind unwind) + add_dependencies(install-unwind-stripped unwind) + endif() + if(LIBUNWIND_INSTALL_HEADERS) add_dependencies(install-unwind install-unwind-headers) add_dependencies(install-unwind-stripped install-unwind-headers-stripped) diff --git a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp index 5cb825e2fd3e9b..cd2e0e3431314a 100644 --- a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp +++ b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp @@ -29,34 +29,34 @@ 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 +template class CompactUnwinder_x86 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A &addressSpace, - R ®isters); + Registers_x86 ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, R ®isters); + static void frameUnwind(A &addressSpace, Registers_x86 ®isters); static void framelessUnwind(A &addressSpace, typename A::pint_t returnAddressLocation, - R ®isters); + Registers_x86 ®isters); static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, - R ®isters); + Registers_x86 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, R ®isters, bool indirectStackSize); + A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86::stepWithCompactEncoding( +template +int CompactUnwinder_x86::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, R ®isters) { + A &addressSpace, Registers_x86 ®isters) { switch (compactEncoding & UNWIND_X86_MODE_MASK) { case UNWIND_X86_MODE_EBP_FRAME: return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, @@ -71,10 +71,10 @@ int CompactUnwinder_x86::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( +template +int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, R ®isters) { + A &addressSpace, Registers_x86 ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -87,19 +87,19 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( // no register saved in this slot break; case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEBX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setECX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEDX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEDI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); + registers.setESI(addressSpace.get32(savedRegisters)); break; default: (void)functionStart; @@ -115,10 +115,10 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint32_t functionStart, - A &addressSpace, R ®isters, bool indirectStackSize) { + A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -204,22 +204,22 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEBX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setECX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEDX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEDI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); + registers.setESI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EBP: - registers.setEBP(addressSpace.get32(savedRegisters), savedRegisters); + registers.setEBP(addressSpace.get32(savedRegisters)); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -234,26 +234,26 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86::frameUnwind(A &addressSpace, - R ®isters) { +template +void CompactUnwinder_x86::frameUnwind(A &addressSpace, + Registers_x86 ®isters) { typename A::pint_t bp = registers.getEBP(); // ebp points to old ebp - registers.setEBP(addressSpace.get32(bp), bp); + registers.setEBP(addressSpace.get32(bp)); // old esp is ebp less saved ebp and return address - registers.setSP((uint32_t)bp + 8, 0); + registers.setSP((uint32_t)bp + 8); // pop return address into eip - registers.setIP(addressSpace.get32(bp + 4), bp + 4); + registers.setIP(addressSpace.get32(bp + 4)); } -template -void CompactUnwinder_x86::framelessUnwind( +template +void CompactUnwinder_x86::framelessUnwind( A &addressSpace, typename A::pint_t returnAddressLocation, - R ®isters) { + Registers_x86 ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get32(returnAddressLocation), returnAddressLocation); + registers.setIP(addressSpace.get32(returnAddressLocation)); // old esp is before return address - registers.setSP((uint32_t)returnAddressLocation + 4, 0); + registers.setSP((uint32_t)returnAddressLocation + 4); } #endif // _LIBUNWIND_TARGET_I386 @@ -261,33 +261,33 @@ void CompactUnwinder_x86::framelessUnwind( #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 +template class CompactUnwinder_x86_64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - R ®isters); + Registers_x86_64 ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, R ®isters); + static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, - R ®isters); + Registers_x86_64 ®isters); static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - R ®isters); + Registers_x86_64 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, R ®isters, bool indirectStackSize); + A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86_64::stepWithCompactEncoding( +template +int CompactUnwinder_x86_64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, R ®isters) { + A &addressSpace, Registers_x86_64 ®isters) { switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { case UNWIND_X86_64_MODE_RBP_FRAME: return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, @@ -302,10 +302,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, R ®isters) { + A &addressSpace, Registers_x86_64 ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -318,19 +318,19 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( // no register saved in this slot break; case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); + registers.setRBX(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR12(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR13(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR14(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR15(addressSpace.get64(savedRegisters)); break; default: (void)functionStart; @@ -346,10 +346,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, - R ®isters, bool indirectStackSize) { + Registers_x86_64 ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -435,22 +435,22 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); + registers.setRBX(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR12(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR13(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR14(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); + registers.setR15(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_RBP: - registers.setRBP(addressSpace.get64(savedRegisters), savedRegisters); + registers.setRBP(addressSpace.get64(savedRegisters)); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -465,26 +465,26 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, - R ®isters) { +template +void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, + Registers_x86_64 ®isters) { uint64_t rbp = registers.getRBP(); // ebp points to old ebp - registers.setRBP(addressSpace.get64(rbp), rbp); + registers.setRBP(addressSpace.get64(rbp)); // old esp is ebp less saved ebp and return address - registers.setSP(rbp + 16, 0); + registers.setSP(rbp + 16); // pop return address into eip - registers.setIP(addressSpace.get64(rbp + 8), rbp + 8); + registers.setIP(addressSpace.get64(rbp + 8)); } -template -void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, - uint64_t returnAddressLocation, - R ®isters) { +template +void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, + uint64_t returnAddressLocation, + Registers_x86_64 ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get64(returnAddressLocation), returnAddressLocation); + registers.setIP(addressSpace.get64(returnAddressLocation)); // old esp is before return address - registers.setSP(returnAddressLocation + 8, 0); + registers.setSP(returnAddressLocation + 8); } #endif // _LIBUNWIND_TARGET_X86_64 @@ -493,13 +493,13 @@ void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, #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 +template class CompactUnwinder_arm64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - R ®isters); + Registers_arm64 ®isters); private: typename A::pint_t pint_t; @@ -507,16 +507,16 @@ class CompactUnwinder_arm64 { static int stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - R ®isters); + Registers_arm64 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, R ®isters); + A &addressSpace, Registers_arm64 ®isters); }; -template -int CompactUnwinder_arm64::stepWithCompactEncoding( +template +int CompactUnwinder_arm64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, R ®isters) { + A &addressSpace, Registers_arm64 ®isters) { switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: return stepWithCompactEncodingFrame(compactEncoding, functionStart, @@ -528,43 +528,43 @@ int CompactUnwinder_arm64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - R ®isters) { + Registers_arm64 ®isters) { uint32_t stackSize = 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); uint64_t savedRegisterLoc = registers.getSP() + stackSize; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } @@ -601,49 +601,55 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( savedRegisterLoc -= 8; } + // We load the link register prior to setting the new SP as the authentication + // schema for LR entangles the SP of the old frame into the diversifier. + Registers_arm64::reg_t linkRegister = registers.getRegister(UNW_AARCH64_LR); + // subtract stack size off of sp - registers.setSP(savedRegisterLoc, 0); + registers.setSP(savedRegisterLoc); - // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_AARCH64_LR), 0); + // Set pc to be value in lr. This needs to be performed after the new SP has + // been set, as the PC authentication schema entangles the SP of the new + // frame. + registers.setIP(linkRegister); return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrame( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrame( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - R ®isters) { - uint64_t savedRegisterLoc = registers.getFP() - 8; + Registers_arm64 ®isters) { + Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } @@ -680,13 +686,18 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrame( savedRegisterLoc -= 8; } - uint64_t fp = registers.getFP(); + Registers_arm64::reg_t fp = registers.getFP(); + // fp points to old fp - registers.setFP(addressSpace.get64(fp), fp); - // old sp is fp less saved fp and lr - registers.setSP(fp + 16, 0); + registers.setFP(addressSpace.get64(fp)); + + // Old sp is fp less saved fp and lr. We need to set this prior to setting + // the lr as the pointer authentication schema for the lr incorporates the + // sp as part of the diversifier. + registers.setSP(fp + 16); + // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8), fp + 8); + registers.setIP(addressSpace.get64(fp + 8)); return UNW_STEP_SUCCESS; } diff --git a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp index 32112839042b58..165c4a99e9a92f 100644 --- a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp @@ -22,7 +22,6 @@ #include "dwarf2.h" #include "libunwind_ext.h" - namespace libunwind { @@ -34,8 +33,10 @@ class DwarfInstructions { typedef typename A::pint_t pint_t; typedef typename A::sint_t sint_t; - static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, - R ®isters, bool &isSignalFrame, bool stage2); + static int stepWithDwarf(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, + pint_t fdeStart, R ®isters, bool &isSignalFrame, + bool stage2); private: @@ -56,8 +57,7 @@ class DwarfInstructions { const R ®isters, pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg, - pint_t& location); + pint_t cfa, const RegisterLocation &savedReg); static double getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, @@ -65,9 +65,10 @@ class DwarfInstructions { static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, const R ®isters) { - if (prolog.cfaRegister != 0) - return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + - prolog.cfaRegisterOffset); + if (prolog.cfaRegister != 0) { + uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister); + return (pint_t)(cfaRegister + prolog.cfaRegisterOffset); + } if (prolog.cfaExpression != 0) return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0); @@ -93,28 +94,24 @@ template uint64_t getSparcWCookie(const R &, long) { template typename A::pint_t DwarfInstructions::getSavedRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg, - typename A::pint_t& location) { + const RegisterLocation &savedReg) { switch (savedReg.location) { case CFI_Parser::kRegisterInCFA: - location = cfa + (pint_t)savedReg.value; - return (pint_t)addressSpace.getP(location); + return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); case CFI_Parser::kRegisterInCFADecrypt: // sparc64 specific return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^ getSparcWCookie(registers, 0)); case CFI_Parser::kRegisterAtExpression: - location = evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa); - return (pint_t)addressSpace.getP(location); + return (pint_t)addressSpace.getRegister(evaluateExpression( + (pint_t)savedReg.value, addressSpace, registers, cfa)); case CFI_Parser::kRegisterIsExpression: - location = 0; return evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa); + case CFI_Parser::kRegisterInRegister: - location = 0; return registers.getRegister((int)savedReg.value); case CFI_Parser::kRegisterUndefined: return 0; @@ -184,12 +181,11 @@ bool DwarfInstructions::isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, PrologInfo &prolog) { pint_t raSignState; - pint_t location; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; if (regloc.location == CFI_Parser::kRegisterUnused) raSignState = static_cast(regloc.value); else - raSignState = getSavedRegister(addressSpace, registers, cfa, regloc, location); + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); // Only bit[0] is meaningful. return raSignState & 0x01; @@ -201,12 +197,11 @@ bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, pint_t cfa, PrologInfo &prolog) { pint_t raSignState; - pint_t location; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; if (regloc.location == CFI_Parser::kRegisterUnused) raSignState = static_cast(regloc.value); else - raSignState = getSavedRegister(addressSpace, registers, cfa, regloc, location); + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); // Only bit[1] is meaningful. return raSignState & 0x02; @@ -214,16 +209,16 @@ bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, #endif template -int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, - pint_t fdeStart, R ®isters, - bool &isSignalFrame, bool stage2) { +int DwarfInstructions::stepWithDwarf( + A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart, + R ®isters, bool &isSignalFrame, bool stage2) { FDE_Info fdeInfo; CIE_Info cieInfo; if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL) { PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { + if (CFI_Parser::template parseFDEInstructions( + addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // get pointer to cfa (architecture specific) pint_t cfa = getCFA(addressSpace, prolog, registers); @@ -231,7 +226,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // __unw_step_stage2 is not used for cross unwinding, so we use // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are // building for AArch64 natively. -#if 0 // defined(__aarch64__) +#if defined(__aarch64__) if (stage2 && cieInfo.mteTaggedFrame) { pint_t sp = registers.getSP(); pint_t p = sp; @@ -269,10 +264,9 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // // We set the SP here to the CFA, allowing for it to be overridden // by a CFI directive later on. - newRegisters.setSP(cfa, 0); + newRegisters.setSP(cfa); - pint_t returnAddress = 0; - pint_t returnAddressLocation = 0; + typename R::reg_t returnAddress = 0; constexpr int lastReg = R::lastDwarfRegNum(); static_assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg, @@ -290,23 +284,13 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, newRegisters.setVectorRegister( i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else if (i == (int)cieInfo.returnAddressRegister) { + else if (i == (int)cieInfo.returnAddressRegister) returnAddress = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i], - returnAddressLocation); - if (registers.validRegister(i)) { - newRegisters.setRegister(i, returnAddress, returnAddressLocation); - } - } - else if (registers.validRegister(i)) { - pint_t value; - pint_t location; - value = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i], - location); - - newRegisters.setRegister(i, value, location); - } + prolog.savedRegisters[i]); + else if (registers.validRegister(i)) + newRegisters.setRegister( + i, getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i])); else return UNW_EBADREG; } else if (i == (int)cieInfo.returnAddressRegister) { @@ -318,7 +302,16 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, isSignalFrame = cieInfo.isSignalFrame; -#if defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_AARCH64) && \ + !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // There are two ways of return address signing: pac-ret (enabled via + // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of + // Apple's arm64e or experimental pauthtest ABI on Linux). The code + // below handles signed RA for pac-ret, while ptrauth-returns uses + // different logic. + // TODO: unify logic for both cases, see + // https://github.com/llvm/llvm-project/issues/160110 + // // If the target is aarch64 then the return address may have been signed // using the v8.3 pointer authentication extensions. The original // return address needs to be authenticated before the return address is @@ -418,7 +411,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // Return address is address after call site instruction, so setting IP to // that does simulates a return. - newRegisters.setIP(returnAddress, returnAddressLocation); + newRegisters.setIP(returnAddress); // Simulate the step by replacing the register set with the new ones. registers = newRegisters; diff --git a/src/native/external/llvm-libunwind/src/DwarfParser.hpp b/src/native/external/llvm-libunwind/src/DwarfParser.hpp index a18b7397b996cb..22de49023cb452 100644 --- a/src/native/external/llvm-libunwind/src/DwarfParser.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfParser.hpp @@ -23,6 +23,10 @@ #include "config.h" +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) +#include +#endif + namespace libunwind { /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. @@ -33,6 +37,7 @@ template class CFI_Parser { public: typedef typename A::pint_t pint_t; + typedef pint_t __ptrauth_unwind_cie_info_personality personality_t; /// Information encoded in a CIE (Common Information Entry) struct CIE_Info { @@ -43,7 +48,7 @@ class CFI_Parser { uint8_t lsdaEncoding; uint8_t personalityEncoding; uint8_t personalityOffsetInCIE; - pint_t personality; + personality_t personality; uint32_t codeAlignFactor; int dataAlignFactor; bool isSignalFrame; @@ -155,14 +160,17 @@ class CFI_Parser { } }; - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, - CIE_Info *cieInfo); + template + static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, + pint_t ehSectionStart, size_t sectionLength, + pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, FDE_Info *fdeInfo, CIE_Info *cieInfo, bool useCIEInfo = false); + template static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, + const CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results); static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); @@ -234,9 +242,12 @@ const char *CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, /// Scan an eh_frame section to find an FDE for a pc template -bool CFI_Parser::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - size_t sectionLength, pint_t fdeHint, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { +template +bool CFI_Parser::findFDE(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, + pint_t ehSectionStart, size_t sectionLength, + pint_t fdeHint, FDE_Info *fdeInfo, + CIE_Info *cieInfo) { //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) @@ -369,6 +380,7 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, cieInfo->returnAddressRegister = (uint8_t)raReg; // parse augmentation data based on augmentation string const char *result = NULL; + pint_t resultAddr = 0; if (addressSpace.get8(strStart) == 'z') { // parse augmentation data length addressSpace.getULEB128(p, cieContentEnd); @@ -377,13 +389,41 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, case 'z': cieInfo->fdesHaveAugmentationData = true; break; - case 'P': + case 'P': { cieInfo->personalityEncoding = addressSpace.get8(p); ++p; cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); - cieInfo->personality = addressSpace - .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); + pint_t personality = addressSpace.getEncodedP( + p, cieContentEnd, cieInfo->personalityEncoding, + /*datarelBase=*/0, &resultAddr); +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + if (personality) { + // The GOT for the personality function was signed address + // authenticated. Manually re-sign with the CIE_Info::personality + // schema. If we could guarantee the encoding of the personality we + // could avoid this by simply giving resultAddr the correct ptrauth + // schema and performing an assignment. +#if defined(__arm64e__) + const auto oldDiscriminator = resultAddr; +#else + const auto oldDiscriminator = ptrauth_blend_discriminator( + (void *)resultAddr, __ptrauth_unwind_pauthtest_personality_disc); +#endif + const auto discriminator = ptrauth_blend_discriminator( + &cieInfo->personality, + __ptrauth_unwind_cie_info_personality_disc); + void *signedPtr = ptrauth_auth_and_resign( + (void *)personality, ptrauth_key_function_pointer, + oldDiscriminator, ptrauth_key_function_pointer, discriminator); + personality = (pint_t)signedPtr; + } +#endif + // We use memmove to set the CIE personality as we have already + // re-signed the pointer to the correct schema. + memmove((void *)&cieInfo->personality, (void *)&personality, + sizeof(personality)); break; + } case 'L': cieInfo->lsdaEncoding = addressSpace.get8(p); ++p; @@ -417,10 +457,10 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE template -bool CFI_Parser::parseFDEInstructions(A &addressSpace, - const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - int arch, PrologInfo *results) { +template +bool CFI_Parser::parseFDEInstructions( + A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) { // Alloca is used for the allocation of the rememberStack entries. It removes // the dependency on new/malloc but the below for loop can not be refactored // into functions. Entry could be saved during the processing of a CIE and @@ -454,7 +494,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, static_cast(instructionsEnd)); // see DWARF Spec, section 6.4.2 for details on unwind opcodes - while ((p < instructionsEnd) && (codeOffset <= pcoffset)) { + while ((p < instructionsEnd) && (codeOffset < pcoffset)) { uint64_t reg; uint64_t reg2; int64_t offset; @@ -808,12 +848,10 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, initialState); - // When calculating the value of the PC, it is assumed that the CFI - // instruction is placed before the signing instruction, however it is - // placed after. Because of this, we need to take into account the CFI - // instruction is one instruction call later than expected, and reduce - // the PC value by 4 bytes to compensate. - results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; + // When using Feat_PAuthLR, the PC value needs to be captured so that + // during unwinding, the correct PC value is used for re-authentication. + // It is assumed that the CFI is placed before the signing instruction. + results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset; _LIBUNWIND_TRACE_DWARF( "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", static_cast(results->ptrAuthDiversifier)); diff --git a/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp b/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp index 0662a1321e2c75..b5d927027f64c1 100644 --- a/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp +++ b/src/native/external/llvm-libunwind/src/EHHeaderParser.hpp @@ -37,8 +37,9 @@ template class EHHeaderParser { static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo); - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, + template + static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, + pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo); @@ -112,8 +113,10 @@ bool EHHeaderParser::decodeTableEntry( } template -bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, - uint32_t sectionLength, +template +bool EHHeaderParser::findFDE(A &addressSpace, + typename R::link_hardened_reg_arg_t pc, + pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo) { pint_t ehHdrEnd = ehHdrStart + sectionLength; diff --git a/src/native/external/llvm-libunwind/src/Registers.hpp b/src/native/external/llvm-libunwind/src/Registers.hpp index 5daa35a3241885..474b17461bf77e 100644 --- a/src/native/external/llvm-libunwind/src/Registers.hpp +++ b/src/native/external/llvm-libunwind/src/Registers.hpp @@ -15,9 +15,15 @@ #include #include -#include "cet_unwind.h" #include "config.h" #include "libunwind.h" +#include "libunwind_ext.h" +#include "shadow_stack_unwind.h" + +#if __has_include() +#include +#define HAVE_SYS_AUXV_H +#endif namespace libunwind { @@ -48,7 +54,7 @@ class _LIBUNWIND_HIDDEN Registers_x86; extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); #if defined(_LIBUNWIND_USE_CET) -extern "C" void *__libunwind_cet_get_jump_target() { +extern "C" void *__libunwind_shstk_get_jump_target() { return reinterpret_cast(&__libunwind_Registers_x86_jumpto); } #endif @@ -60,10 +66,13 @@ class _LIBUNWIND_HIDDEN Registers_x86 { Registers_x86(); Registers_x86(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value, uint32_t location); - uint32_t getRegisterLocation(int num) const; + void setRegister(int num, uint32_t value); bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -78,21 +87,21 @@ class _LIBUNWIND_HIDDEN Registers_x86 { static int getArch() { return REGISTERS_X86; } uint32_t getSP() const { return _registers.__esp; } - void setSP(uint32_t value, uint32_t location) { _registers.__esp = value; _registerLocations.__esp = location; } + void setSP(uint32_t value) { _registers.__esp = value; } uint32_t getIP() const { return _registers.__eip; } - void setIP(uint32_t value, uint32_t location) { _registers.__eip = value; _registerLocations.__eip = location; } + void setIP(uint32_t value) { _registers.__eip = value; } uint32_t getEBP() const { return _registers.__ebp; } - void setEBP(uint32_t value, uint32_t location) { _registers.__ebp = value; _registerLocations.__ebp = location; } + void setEBP(uint32_t value) { _registers.__ebp = value; } uint32_t getEBX() const { return _registers.__ebx; } - void setEBX(uint32_t value, uint32_t location) { _registers.__ebx = value; _registerLocations.__ebx = location; } + void setEBX(uint32_t value) { _registers.__ebx = value; } uint32_t getECX() const { return _registers.__ecx; } - void setECX(uint32_t value, uint32_t location) { _registers.__ecx = value; _registerLocations.__ecx = location; } + void setECX(uint32_t value) { _registers.__ecx = value; } uint32_t getEDX() const { return _registers.__edx; } - void setEDX(uint32_t value, uint32_t location) { _registers.__edx = value; _registerLocations.__edx = location; } + void setEDX(uint32_t value) { _registers.__edx = value; } uint32_t getESI() const { return _registers.__esi; } - void setESI(uint32_t value, uint32_t location) { _registers.__esi = value; _registerLocations.__esi = location; } + void setESI(uint32_t value) { _registers.__esi = value; } uint32_t getEDI() const { return _registers.__edi; } - void setEDI(uint32_t value, uint32_t location) { _registers.__edi = value; _registerLocations.__edi = location; } + void setEDI(uint32_t value) { _registers.__edi = value; } private: struct GPRs { @@ -113,32 +122,18 @@ class _LIBUNWIND_HIDDEN Registers_x86 { unsigned int __fs; unsigned int __gs; }; - struct GPRLocations { - unsigned int __eax; - unsigned int __ebx; - unsigned int __ecx; - unsigned int __edx; - unsigned int __edi; - unsigned int __esi; - unsigned int __ebp; - unsigned int __esp; - unsigned int __eip; - }; GPRs _registers; - GPRLocations _registerLocations; }; inline Registers_x86::Registers_x86(const void *registers) { static_assert((check_fit::does_fit), "x86 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86::Registers_x86() { memset(&_registers, 0, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86::validRegister(int regNum) const { @@ -187,31 +182,25 @@ inline uint32_t Registers_x86::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86 register"); } -inline void Registers_x86::setRegister(int regNum, uint32_t value, uint32_t location) { +inline void Registers_x86::setRegister(int regNum, uint32_t value) { switch (regNum) { case UNW_REG_IP: _registers.__eip = value; - _registerLocations.__eip = location; return; case UNW_REG_SP: _registers.__esp = value; - _registerLocations.__esp = location; return; case UNW_X86_EAX: _registers.__eax = value; - _registerLocations.__eax = location; return; case UNW_X86_ECX: _registers.__ecx = value; - _registerLocations.__ecx = location; return; case UNW_X86_EDX: _registers.__edx = value; - _registerLocations.__edx = location; return; case UNW_X86_EBX: _registers.__ebx = value; - _registerLocations.__ebx = location; return; #if !defined(__APPLE__) case UNW_X86_ESP: @@ -219,7 +208,6 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value, uint32_t loca case UNW_X86_EBP: #endif _registers.__ebp = value; - _registerLocations.__ebp = location; return; #if !defined(__APPLE__) case UNW_X86_EBP: @@ -227,46 +215,17 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value, uint32_t loca case UNW_X86_ESP: #endif _registers.__esp = value; - _registerLocations.__esp = location; return; case UNW_X86_ESI: _registers.__esi = value; - _registerLocations.__esi = location; return; case UNW_X86_EDI: _registers.__edi = value; - _registerLocations.__edi = location; return; } _LIBUNWIND_ABORT("unsupported x86 register"); } -inline uint32_t Registers_x86::getRegisterLocation(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registerLocations.__eip; - case UNW_REG_SP: - return _registerLocations.__esp; - case UNW_X86_EAX: - return _registerLocations.__eax; - case UNW_X86_ECX: - return _registerLocations.__ecx; - case UNW_X86_EDX: - return _registerLocations.__edx; - case UNW_X86_EBX: - return _registerLocations.__ebx; - case UNW_X86_EBP: - return _registerLocations.__ebp; - case UNW_X86_ESP: - return _registerLocations.__esp; - case UNW_X86_ESI: - return _registerLocations.__esi; - case UNW_X86_EDI: - return _registerLocations.__edi; - } - _LIBUNWIND_ABORT("unsupported x86 register"); -} - inline const char *Registers_x86::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -319,7 +278,7 @@ class _LIBUNWIND_HIDDEN Registers_x86_64; extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); #if defined(_LIBUNWIND_USE_CET) -extern "C" void *__libunwind_cet_get_jump_target() { +extern "C" void *__libunwind_shstk_get_jump_target() { return reinterpret_cast(&__libunwind_Registers_x86_64_jumpto); } #endif @@ -329,10 +288,13 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { Registers_x86_64(); Registers_x86_64(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value, uint64_t location); - uint64_t getRegisterLocation(int num) const; + void setRegister(int num, uint64_t value); bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -347,21 +309,21 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { static int getArch() { return REGISTERS_X86_64; } uint64_t getSP() const { return _registers.__rsp; } - void setSP(uint64_t value, uint64_t location) { _registers.__rsp = value; _registerLocations.__rsp = location;} + void setSP(uint64_t value) { _registers.__rsp = value; } uint64_t getIP() const { return _registers.__rip; } - void setIP(uint64_t value, uint64_t location) { _registers.__rip = value; _registerLocations.__rip = location; } + void setIP(uint64_t value) { _registers.__rip = value; } uint64_t getRBP() const { return _registers.__rbp; } - void setRBP(uint64_t value, uint64_t location) { _registers.__rbp = value; _registerLocations.__rbp = location; } + void setRBP(uint64_t value) { _registers.__rbp = value; } uint64_t getRBX() const { return _registers.__rbx; } - void setRBX(uint64_t value, uint64_t location) { _registers.__rbx = value; _registerLocations.__rbx = location; } + void setRBX(uint64_t value) { _registers.__rbx = value; } uint64_t getR12() const { return _registers.__r12; } - void setR12(uint64_t value, uint64_t location) { _registers.__r12 = value; _registerLocations.__r12 = location; } + void setR12(uint64_t value) { _registers.__r12 = value; } uint64_t getR13() const { return _registers.__r13; } - void setR13(uint64_t value, uint64_t location) { _registers.__r13 = value; _registerLocations.__r13 = location; } + void setR13(uint64_t value) { _registers.__r13 = value; } uint64_t getR14() const { return _registers.__r14; } - void setR14(uint64_t value, uint64_t location) { _registers.__r14 = value; _registerLocations.__r14 = location; } + void setR14(uint64_t value) { _registers.__r14 = value; } uint64_t getR15() const { return _registers.__r15; } - void setR15(uint64_t value, uint64_t location) { _registers.__r15 = value; _registerLocations.__r15 = location; } + void setR15(uint64_t value) { _registers.__r15 = value; } private: struct GPRs { @@ -390,27 +352,7 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { uint64_t __padding; // 16-byte align #endif }; - struct GPRLocations { - uint64_t __rax; - uint64_t __rbx; - uint64_t __rcx; - uint64_t __rdx; - uint64_t __rdi; - uint64_t __rsi; - uint64_t __rbp; - uint64_t __rsp; - uint64_t __r8; - uint64_t __r9; - uint64_t __r10; - uint64_t __r11; - uint64_t __r12; - uint64_t __r13; - uint64_t __r14; - uint64_t __r15; - uint64_t __rip; - }; GPRs _registers; - GPRLocations _registerLocations; #if defined(_WIN64) v128 _xmm[16]; #endif @@ -420,12 +362,10 @@ inline Registers_x86_64::Registers_x86_64(const void *registers) { static_assert((check_fit::does_fit), "x86_64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86_64::Registers_x86_64() { memset(&_registers, 0, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86_64::validRegister(int regNum) const { @@ -483,122 +423,62 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86_64 register"); } -inline uint64_t Registers_x86_64::getRegisterLocation(int regNum) const { - switch (regNum) { - case UNW_REG_IP: - return _registerLocations.__rip; - case UNW_REG_SP: - return _registerLocations.__rsp; - case UNW_X86_64_RAX: - return _registerLocations.__rax; - case UNW_X86_64_RDX: - return _registerLocations.__rdx; - case UNW_X86_64_RCX: - return _registerLocations.__rcx; - case UNW_X86_64_RBX: - return _registerLocations.__rbx; - case UNW_X86_64_RSI: - return _registerLocations.__rsi; - case UNW_X86_64_RDI: - return _registerLocations.__rdi; - case UNW_X86_64_RBP: - return _registerLocations.__rbp; - case UNW_X86_64_RSP: - return _registerLocations.__rsp; - case UNW_X86_64_R8: - return _registerLocations.__r8; - case UNW_X86_64_R9: - return _registerLocations.__r9; - case UNW_X86_64_R10: - return _registerLocations.__r10; - case UNW_X86_64_R11: - return _registerLocations.__r11; - case UNW_X86_64_R12: - return _registerLocations.__r12; - case UNW_X86_64_R13: - return _registerLocations.__r13; - case UNW_X86_64_R14: - return _registerLocations.__r14; - case UNW_X86_64_R15: - return _registerLocations.__r15; - } - _LIBUNWIND_ABORT("unsupported x86_64 register"); -} - -inline void Registers_x86_64::setRegister(int regNum, uint64_t value, uint64_t location) { +inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: case UNW_X86_64_RIP: _registers.__rip = value; - _registerLocations.__rip = location; return; case UNW_REG_SP: _registers.__rsp = value; - _registerLocations.__rsp = location; return; case UNW_X86_64_RAX: _registers.__rax = value; - _registerLocations.__rax = location; return; case UNW_X86_64_RDX: _registers.__rdx = value; - _registerLocations.__rdx = location; return; case UNW_X86_64_RCX: _registers.__rcx = value; - _registerLocations.__rcx = location; return; case UNW_X86_64_RBX: _registers.__rbx = value; - _registerLocations.__rbx = location; return; case UNW_X86_64_RSI: _registers.__rsi = value; - _registerLocations.__rsi = location; return; case UNW_X86_64_RDI: _registers.__rdi = value; - _registerLocations.__rdi = location; return; case UNW_X86_64_RBP: _registers.__rbp = value; - _registerLocations.__rbp = location; return; case UNW_X86_64_RSP: _registers.__rsp = value; - _registerLocations.__rsp = location; return; case UNW_X86_64_R8: _registers.__r8 = value; - _registerLocations.__r8 = location; return; case UNW_X86_64_R9: _registers.__r9 = value; - _registerLocations.__r9 = location; return; case UNW_X86_64_R10: _registers.__r10 = value; - _registerLocations.__r10 = location; return; case UNW_X86_64_R11: _registers.__r11 = value; - _registerLocations.__r11 = location; return; case UNW_X86_64_R12: _registers.__r12 = value; - _registerLocations.__r12 = location; return; case UNW_X86_64_R13: _registers.__r13 = value; - _registerLocations.__r13 = location; return; case UNW_X86_64_R14: _registers.__r14 = value; - _registerLocations.__r14 = location; return; case UNW_X86_64_R15: _registers.__r15 = value; - _registerLocations.__r15 = location; return; } _LIBUNWIND_ABORT("unsupported x86_64 register"); @@ -731,6 +611,10 @@ class _LIBUNWIND_HIDDEN Registers_ppc { Registers_ppc(); Registers_ppc(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); @@ -1303,10 +1187,13 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 { Registers_ppc64(); Registers_ppc64(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value, uint64_t location); - uint64_t getRegisterLocation(int num) const; + void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -1949,88 +1836,183 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { /// Registers_arm64 holds the register state of a thread in a 64-bit arm /// process. class _LIBUNWIND_HIDDEN Registers_arm64; -extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); +extern "C" int64_t __libunwind_Registers_arm64_za_disable(); +extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, + unsigned walkedFrames); #if defined(_LIBUNWIND_USE_GCS) -extern "C" void *__libunwind_cet_get_jump_target() { +extern "C" void *__libunwind_shstk_get_jump_target() { return reinterpret_cast(&__libunwind_Registers_arm64_jumpto); } #endif class _LIBUNWIND_HIDDEN Registers_arm64 { public: - Registers_arm64(); + Registers_arm64() = default; Registers_arm64(const void *registers); + Registers_arm64(const Registers_arm64 &); + Registers_arm64 &operator=(const Registers_arm64 &); + + typedef uint64_t reg_t; + typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t; + + // Use `link_hardened_reg_arg_t` to pass values of `link_reg_t` type as + // function arguments. We need to use a const l-value reference to keep + // signature of `__ptrauth`-qualified values of `link_reg_t` type on AArch64 + // PAuth-enabled ABI intact. Passing the raw pointer by value would cause + // authentication on the caller side and make the pointer prone to + // substitution if spilled to the stack in the callee. + typedef const link_reg_t &link_hardened_reg_arg_t; bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value, uint64_t location); + void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); - uint64_t getRegisterLocation(int regNum) const; static const char *getRegisterName(int num); - void jumpto() { __libunwind_Registers_arm64_jumpto(this); } + void jumpto(unsigned walkedFrames = 0) { + zaDisable(); + __libunwind_Registers_arm64_jumpto(this, walkedFrames); + } +#ifdef _LIBUNWIND_TRACE_RET_INJECT + _LIBUNWIND_TRACE_NO_INLINE + void returnto(unsigned walkedFrames) { jumpto(walkedFrames); } +#endif static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } static int getArch() { return REGISTERS_ARM64; } uint64_t getSP() const { return _registers.__sp; } - void setSP(uint64_t value, uint64_t location) { _registers.__sp = value; } - uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value, uint64_t location) { _registers.__pc = value; } - uint64_t getFP() const { return _registers.__fp; } - void setFP(uint64_t value, uint64_t location) { _registers.__fp = value; } + void setSP(uint64_t value) { _registers.__sp = value; } + uint64_t getIP() const { + uint64_t value = _registers.__pc; +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // Note the value of the PC was signed to its address in the register state + // but everyone else expects it to be sign by the SP, so convert on return. + value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc, + ptrauth_key_return_address, + &_registers.__pc, + ptrauth_key_return_address, + getSP()); +#endif + return value; + } + void setIP(uint64_t value) { +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // Note the value which was set should have been signed with the SP. + // We then resign with the slot we are being stored in to so that both SP + // and LR can't be spoofed at the same time. + value = (uint64_t)ptrauth_auth_and_resign((void *)value, + ptrauth_key_return_address, + getSP(), + ptrauth_key_return_address, + &_registers.__pc); +#endif + _registers.__pc = value; + } + uint64_t getFP() const { return _registers.__fp; } + void setFP(uint64_t value) { _registers.__fp = value; } + +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + void + loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister, + link_reg_t *referenceAuthedLinkRegister) { + // If we are in an arm64/arm64e frame, then the PC should have been signed + // with the SP + *referenceAuthedLinkRegister = + (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister, + ptrauth_key_return_address, + _registers.__sp); + } +#endif private: + uint64_t lazyGetVG() const; + + void zaDisable() const { + if (!_misc_registers.__has_sme) + return; + if (__libunwind_Registers_arm64_za_disable() != 0) + _LIBUNWIND_ABORT("SME ZA disable failed"); + } + + static bool checkHasSME() { +#if defined(HAVE_SYS_AUXV_H) + constexpr int hwcap2_sme = (1 << 23); + unsigned long hwcap2 = getauxval(AT_HWCAP2); + return (hwcap2 & hwcap2_sme) != 0; +#endif + // TODO: Support other platforms. + return false; + } + struct GPRs { - uint64_t __x[29]; // x0-x28 - uint64_t __fp; // Frame pointer x29 - uint64_t __lr; // Link register x30 - uint64_t __sp; // Stack pointer x31 - uint64_t __pc; // Program counter - uint64_t __ra_sign_state; // RA sign state register + uint64_t __x[29] = {}; // x0-x28 + uint64_t __fp = 0; // Frame pointer x29 + uint64_t __lr = 0; // Link register x30 + uint64_t __sp = 0; // Stack pointer x31 + uint64_t __pc = 0; // Program counter + uint64_t __ra_sign_state = 0; // RA sign state register }; - struct GPRLocations { - uint64_t __x[29]; // x0-x28 - uint64_t __fp; // Frame pointer x29 - uint64_t __lr; // Link register x30 - uint64_t __sp; // Stack pointer x31 - uint64_t __pc; // Program counter - uint64_t padding; // 16-byte align + struct Misc { + mutable uint32_t __vg = 0; // Vector Granule + bool __has_sme = checkHasSME(); }; - GPRs _registers; - GPRLocations _registerLocations; - double _vectorHalfRegisters[32]; + GPRs _registers = {}; // Currently only the lower double in 128-bit vectore registers // is perserved during unwinding. We could define new register // numbers (> 96) which mean whole vector registers, then this // struct would need to change to contain whole vector registers. + double _vectorHalfRegisters[32] = {}; + + // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs + // as they do not correspond to physical registers, so do not need to be + // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and + // we don't want to modify the existing offsets for GPRs and FPRs. + Misc _misc_registers; }; inline Registers_arm64::Registers_arm64(const void *registers) { static_assert((check_fit::does_fit), "arm64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); - static_assert( - sizeof(GPRs) == 0x110, + static_assert(sizeof(GPRs) == 0x110, "expected VFP registers to be at offset 272"); memcpy(_vectorHalfRegisters, static_cast(registers) + sizeof(GPRs), sizeof(_vectorHalfRegisters)); + _misc_registers.__vg = 0; + +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // We have to do some pointer authentication fixups after this copy, + // and as part of that we need to load the source pc without + // authenticating so that we maintain the signature for the resigning + // performed by setIP. + uint64_t pcRegister = 0; + memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc), + sizeof(pcRegister)); + setIP(pcRegister); +#endif } -inline Registers_arm64::Registers_arm64() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); - memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); +inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) { + *this = other; +} + +inline Registers_arm64 & +Registers_arm64::operator=(const Registers_arm64 &other) { + memmove(static_cast(this), &other, sizeof(*this)); + // We perform this step to ensure that we correctly authenticate and re-sign + // the pc after the bitwise copy. + setIP(other.getIP()); + return *this; } inline bool Registers_arm64::validRegister(int regNum) const { @@ -2044,64 +2026,64 @@ inline bool Registers_arm64::validRegister(int regNum) const { return false; if (regNum == UNW_AARCH64_RA_SIGN_STATE) return true; + if (regNum == UNW_AARCH64_VG) + return true; if ((regNum > 32) && (regNum < 64)) return false; return true; } +inline uint64_t Registers_arm64::lazyGetVG() const { + if (!_misc_registers.__vg) { +#if defined(__aarch64__) + register uint64_t vg asm("x0"); + asm(".inst 0x04e0e3e0" // CNTD x0 + : "=r"(vg)); + _misc_registers.__vg = vg; +#else + _LIBUNWIND_ABORT("arm64 VG undefined"); +#endif + } + return _misc_registers.__vg; +} + inline uint64_t Registers_arm64::getRegister(int regNum) const { if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) - return _registers.__pc; + return getIP(); if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) return _registers.__sp; if (regNum == UNW_AARCH64_RA_SIGN_STATE) return _registers.__ra_sign_state; if (regNum == UNW_AARCH64_FP) - return _registers.__fp; + return getFP(); if (regNum == UNW_AARCH64_LR) return _registers.__lr; + if (regNum == UNW_AARCH64_VG) + return lazyGetVG(); if ((regNum >= 0) && (regNum < 29)) return _registers.__x[regNum]; _LIBUNWIND_ABORT("unsupported arm64 register"); } -inline void Registers_arm64::setRegister(int regNum, uint64_t value, uint64_t location) { - if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) { - _registers.__pc = value; - _registerLocations.__pc = location; - } - else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) { +inline void Registers_arm64::setRegister(int regNum, uint64_t value) { + if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) + setIP(value); + else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) _registers.__sp = value; - _registerLocations.__sp = location; - } else if (regNum == UNW_AARCH64_RA_SIGN_STATE) _registers.__ra_sign_state = value; - else if (regNum == UNW_AARCH64_FP) { - _registers.__fp = value; - _registerLocations.__fp = location; - } - else if (regNum == UNW_AARCH64_LR) { + else if (regNum == UNW_AARCH64_FP) + setFP(value); + else if (regNum == UNW_AARCH64_LR) _registers.__lr = value; - _registerLocations.__lr = location; - } - else if ((regNum >= 0) && (regNum < 29)) { + else if (regNum == UNW_AARCH64_VG) + _misc_registers.__vg = value; + else if ((regNum >= 0) && (regNum < 29)) _registers.__x[regNum] = value; - _registerLocations.__x[regNum] = location; - } else _LIBUNWIND_ABORT("unsupported arm64 register"); } -inline uint64_t Registers_arm64::getRegisterLocation(int regNum) const { - if (regNum == UNW_REG_IP) - return _registerLocations.__pc; - if (regNum == UNW_REG_SP) - return _registerLocations.__sp; - if ((regNum >= 0) && (regNum < 32)) - return _registerLocations.__x[regNum]; - _LIBUNWIND_ABORT("unsupported arm64 register"); -} - inline const char *Registers_arm64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -2285,10 +2267,13 @@ class _LIBUNWIND_HIDDEN Registers_arm { Registers_arm(); Registers_arm(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value, uint32_t location); - uint32_t getRegisterLocation(int num) const; + void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; unw_fpreg_t getFloatRegister(int num); void setFloatRegister(int num, unw_fpreg_t value); @@ -2306,9 +2291,9 @@ class _LIBUNWIND_HIDDEN Registers_arm { static int getArch() { return REGISTERS_ARM; } uint32_t getSP() const { return _registers.__sp; } - void setSP(uint32_t value, uint32_t location) { _registers.__sp = value; _registerLocations.__sp = location; } + void setSP(uint32_t value) { _registers.__sp = value; } uint32_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value, uint32_t location) { _registers.__pc = value; _registerLocations.__pc = location; } + void setIP(uint32_t value) { _registers.__pc = value; } void saveVFPAsX() { assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); @@ -2345,14 +2330,6 @@ class _LIBUNWIND_HIDDEN Registers_arm { }; static void saveVFPWithFSTMD(void*); - - struct GPRLocations { - uint32_t __r[13]; // r0-r12 - uint32_t __sp; // Stack pointer r13 - uint32_t __lr; // Link register r14 - uint32_t __pc; // Program counter r15 - }; - static void saveVFPWithFSTMX(void*); static void saveVFPv3(void*); static void restoreVFPWithFLDMD(void*); @@ -2369,7 +2346,6 @@ class _LIBUNWIND_HIDDEN Registers_arm { // ARM registers GPRs _registers; PseudoRegisters _pseudo_registers; - GPRLocations _registerLocations; // We save floating point registers lazily because we can't know ahead of // time which ones are used. See EHABI #4.7. @@ -2408,7 +2384,6 @@ inline Registers_arm::Registers_arm(const void *registers) // See __unw_getcontext() note about data. memcpy(&_registers, registers, sizeof(_registers)); memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2425,7 +2400,6 @@ inline Registers_arm::Registers_arm() _saved_vfp_d16_d31(false) { memset(&_registers, 0, sizeof(_registers)); memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2492,28 +2466,24 @@ inline uint32_t Registers_arm::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported arm register"); } -inline void Registers_arm::setRegister(int regNum, uint32_t value, uint32_t location) { +inline void Registers_arm::setRegister(int regNum, uint32_t value) { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { _registers.__sp = value; - _registerLocations.__sp = location; return; } if (regNum == UNW_ARM_LR) { _registers.__lr = value; - _registerLocations.__lr = location; return; } if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { _registers.__pc = value; - _registerLocations.__pc = location; return; } if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { _registers.__r[regNum] = value; - _registerLocations.__r[regNum] = location; return; } @@ -2536,22 +2506,6 @@ inline void Registers_arm::setRegister(int regNum, uint32_t value, uint32_t loca _LIBUNWIND_ABORT("unsupported arm register"); } -inline uint32_t Registers_arm::getRegisterLocation(int regNum) const { - if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) - return _registerLocations.__sp; - - if (regNum == UNW_ARM_LR) - return _registerLocations.__lr; - - if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) - return _registerLocations.__pc; - - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) - return _registerLocations.__r[regNum]; - - _LIBUNWIND_ABORT("unsupported arm register"); -} - inline const char *Registers_arm::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -2822,6 +2776,10 @@ class _LIBUNWIND_HIDDEN Registers_or1k { Registers_or1k(); Registers_or1k(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); @@ -3021,6 +2979,10 @@ class _LIBUNWIND_HIDDEN Registers_mips_o32 { Registers_mips_o32(); Registers_mips_o32(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); @@ -3356,6 +3318,10 @@ class _LIBUNWIND_HIDDEN Registers_mips_newabi { Registers_mips_newabi(); Registers_mips_newabi(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); @@ -3659,6 +3625,10 @@ class _LIBUNWIND_HIDDEN Registers_sparc { Registers_sparc(); Registers_sparc(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); @@ -3845,6 +3815,10 @@ class _LIBUNWIND_HIDDEN Registers_sparc64 { Registers_sparc64() = default; Registers_sparc64(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); @@ -4030,6 +4004,10 @@ class _LIBUNWIND_HIDDEN Registers_hexagon { Registers_hexagon(); Registers_hexagon(const void *registers); + typedef uint32_t reg_t; + typedef uint32_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); @@ -4245,16 +4223,19 @@ class _LIBUNWIND_HIDDEN Registers_riscv { Registers_riscv(); Registers_riscv(const void *registers); + typedef ::libunwind::reg_t reg_t; + typedef ::libunwind::reg_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; reg_t getRegister(int num) const; - void setRegister(int num, reg_t value, uint64_t location); + void setRegister(int num, reg_t value); bool validFloatRegister(int num) const; fp_t getFloatRegister(int num) const; void setFloatRegister(int num, fp_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); - uint64_t getRegisterLocation(int num) const; static const char *getRegisterName(int num); void jumpto(); static constexpr int lastDwarfRegNum() { @@ -4263,14 +4244,13 @@ class _LIBUNWIND_HIDDEN Registers_riscv { static int getArch() { return REGISTERS_RISCV; } reg_t getSP() const { return _registers[2]; } - void setSP(reg_t value, uint64_t location) { _registers[2] = value; } + void setSP(reg_t value) { _registers[2] = value; } reg_t getIP() const { return _registers[0]; } - void setIP(reg_t value, uint64_t location) { _registers[0] = value; } + void setIP(reg_t value) { _registers[0] = value; } private: // _registers[0] holds the pc reg_t _registers[32]; - reg_t _registerLocations[32]; # if defined(__riscv_flen) fp_t _floats[32]; # endif @@ -4280,7 +4260,6 @@ inline Registers_riscv::Registers_riscv(const void *registers) { static_assert((check_fit::does_fit), "riscv registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); # if __riscv_xlen == 32 static_assert(sizeof(_registers) == 0x80, "expected float registers to be at offset 128"); @@ -4300,7 +4279,6 @@ inline Registers_riscv::Registers_riscv(const void *registers) { inline Registers_riscv::Registers_riscv() { memset(&_registers, 0, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); # if defined(__riscv_flen) memset(&_floats, 0, sizeof(_floats)); # endif @@ -4331,47 +4309,26 @@ inline reg_t Registers_riscv::getRegister(int regNum) const { return _registers[regNum]; if (regNum == UNW_RISCV_VLENB) { reg_t vlenb; - __asm__("csrr %0, 0xC22" : "=r"(vlenb)); + __asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb)); return vlenb; } _LIBUNWIND_ABORT("unsupported riscv register"); } -inline void Registers_riscv::setRegister(int regNum, reg_t value, uint64_t location) { - if (regNum == UNW_REG_IP) { +inline void Registers_riscv::setRegister(int regNum, reg_t value) { + if (regNum == UNW_REG_IP) _registers[0] = value; - _registerLocations[0] = value; - } else if (regNum == UNW_REG_SP) _registers[2] = value; else if (regNum == UNW_RISCV_X0) /* x0 is hardwired to zero */ return; - else if ((regNum > 0) && (regNum < 32)) { + else if ((regNum > 0) && (regNum < 32)) _registers[regNum] = value; - _registerLocations[regNum - UNW_RISCV_X0] = location; - } else _LIBUNWIND_ABORT("unsupported riscv register"); } -inline uint64_t Registers_riscv::getRegisterLocation(int regNum) const { - if (regNum == UNW_REG_IP) - return _registerLocations[0]; - if (regNum == UNW_REG_SP) - return _registerLocations[2]; - if (regNum == UNW_RISCV_X0) - return 0; - if ((regNum > 0) && (regNum < 32)) - return _registerLocations[regNum]; - if (regNum == UNW_RISCV_VLENB) { - reg_t vlenb; - __asm__("csrr %0, 0xC22" : "=r"(vlenb)); - return vlenb; - } - _LIBUNWIND_ABORT("unsupported riscv register"); -} - inline const char *Registers_riscv::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -4567,6 +4524,10 @@ class _LIBUNWIND_HIDDEN Registers_ve { Registers_ve(); Registers_ve(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); @@ -5010,6 +4971,10 @@ class _LIBUNWIND_HIDDEN Registers_s390x { Registers_s390x(); Registers_s390x(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); @@ -5298,16 +5263,19 @@ class _LIBUNWIND_HIDDEN Registers_loongarch { Registers_loongarch(); Registers_loongarch(const void *registers); + typedef uint64_t reg_t; + typedef uint64_t link_reg_t; + typedef const link_reg_t &link_hardened_reg_arg_t; + bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value, uint64_t location); + void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); - uint64_t getRegisterLocation(int num) const; static const char *getRegisterName(int num); void jumpto(); static constexpr int lastDwarfRegNum() { @@ -5316,23 +5284,17 @@ class _LIBUNWIND_HIDDEN Registers_loongarch { static int getArch() { return REGISTERS_LOONGARCH; } uint64_t getSP() const { return _registers.__r[3]; } - void setSP(uint64_t value, uint64_t location) { _registers.__r[3] = value; } + void setSP(uint64_t value) { _registers.__r[3] = value; } uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value, uint64_t location) { _registers.__pc = value; } + void setIP(uint64_t value) { _registers.__pc = value; } private: - struct GPRs { - uint64_t __r[32]; - uint64_t __pc; - }; - - struct GPRLocations { + struct loongarch_thread_state_t { uint64_t __r[32]; uint64_t __pc; }; - GPRs _registers; - GPRLocations _registerLocations; + loongarch_thread_state_t _registers; #if __loongarch_frlen == 64 double _floats[32]; #endif @@ -5342,7 +5304,6 @@ inline Registers_loongarch::Registers_loongarch(const void *registers) { static_assert((check_fit::does_fit), "loongarch registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); static_assert(sizeof(_registers) == 0x108, "expected float registers to be at offset 264"); #if __loongarch_frlen == 64 @@ -5353,7 +5314,6 @@ inline Registers_loongarch::Registers_loongarch(const void *registers) { inline Registers_loongarch::Registers_loongarch() { memset(&_registers, 0, sizeof(_registers)); - memset(&_registerLocations, 0, sizeof(_registerLocations)); #if __loongarch_frlen == 64 memset(&_floats, 0, sizeof(_floats)); #endif @@ -5378,33 +5338,17 @@ inline uint64_t Registers_loongarch::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported loongarch register"); } -inline void Registers_loongarch::setRegister(int regNum, uint64_t value, uint64_t location) { - if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) { +inline void Registers_loongarch::setRegister(int regNum, uint64_t value) { + if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) _registers.__r[regNum - UNW_LOONGARCH_R0] = value; - _registerLocations.__r[regNum - UNW_LOONGARCH_R0] = location; - } - else if (regNum == UNW_REG_IP) { + else if (regNum == UNW_REG_IP) _registers.__pc = value; - _registerLocations.__pc = location; - } - else if (regNum == UNW_REG_SP) { + else if (regNum == UNW_REG_SP) _registers.__r[3] = value; - _registerLocations.__r[3] = location; - } else _LIBUNWIND_ABORT("unsupported loongarch register"); } -inline uint64_t Registers_loongarch::getRegisterLocation(int regNum) const { - if (regNum == UNW_REG_IP) - return _registerLocations.__pc; - if (regNum == UNW_REG_SP) - return _registerLocations.__r[3]; - if ((regNum >= 0) && (regNum < 32)) - return _registerLocations.__r[regNum]; - _LIBUNWIND_ABORT("unsupported loongarch64 register"); -} - inline const char *Registers_loongarch::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: diff --git a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp index 338c853bca780e..05475c6ac1e2fe 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp @@ -228,7 +228,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { // only by the personality routine. Fortunately, all existing assembler // implementations, including GNU assembler, LLVM integrated assembler, // and ARM assembler, assume that the unwind opcodes come after the - // personality routine address. + // personality rountine address. *off = 1; // First byte is size data. *len = (((data[1] >> 24) & 0xff) + 1) * 4; data++; // Skip the first word, which is the prel31 offset. @@ -271,7 +271,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, sp -= (((uint32_t)byte & 0x3f) << 2) + 4; else sp += ((uint32_t)byte << 2) + 4; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } else { switch (byte & 0xf0) { case 0x80: { @@ -295,7 +295,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, _UVRSD_UINT32, &sp); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp, NULL); + &sp); break; } case 0xa0: { @@ -337,7 +337,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, &sp); sp += 0x204 + (addend << 2); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp, NULL); + &sp); break; } case 0xb3: { @@ -438,7 +438,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, #else (void)hasReturnAddrAuthCode; #endif - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr, NULL); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); } return _URC_CONTINUE_UNWIND; } @@ -589,7 +589,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor // // See #7.4.6 for details. __unw_set_reg(cursor, UNW_REG_IP, - exception_object->unwinder_cache.reserved2, NULL); + exception_object->unwinder_cache.reserved2); resume = false; } @@ -909,7 +909,7 @@ ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, _LIBUNWIND_EXPORT _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep, unw_word_t *pos) { + void *valuep) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " "rep=%d, value=0x%llX)", static_cast(context), regclass, regno, @@ -921,7 +921,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - *(unw_word_t *)valuep,(unw_word_t *)pos) == UNW_ESUCCESS + *(unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: @@ -965,7 +965,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno != 0) return _UVRSR_FAILED; return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), - *(unw_word_t *)valuep, NULL) == UNW_ESUCCESS + *(unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; break; @@ -1071,7 +1071,6 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // computed new stack location. See EHABI #7.5.4 table 3. bool poppedSP = false; uint32_t* sp; - uint32_t* pos; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; @@ -1079,18 +1078,17 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, for (uint32_t i = 0; i < 16; ++i) { if (!(discriminator & static_cast(1 << i))) continue; - pos = sp; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) poppedSP = true; if (_Unwind_VRS_Set(context, regclass, i, - _UVRSD_UINT32, &value, pos) != _UVRSR_OK) { + _UVRSD_UINT32, &value) != _UVRSR_OK) { return _UVRSR_FAILED; } } if (!poppedSP) { return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp, NULL); + _UVRSD_UINT32, &sp); } return _UVRSR_OK; } @@ -1122,14 +1120,14 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, #else #error "Unable to determine endianess" #endif - if (_Unwind_VRS_Set(context, regclass, i, representation, &value, NULL) != + if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != _UVRSR_OK) return _UVRSR_FAILED; } if (representation == _UVRSD_VFPX) ++sp; return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp, NULL); + &sp); } case _UVRSC_PSEUDO: { if (representation != _UVRSD_UINT32 || discriminator != 0) @@ -1141,8 +1139,8 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, return _UVRSR_FAILED; } uint32_t pac = *sp++; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); - return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac, NULL); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac); } } _LIBUNWIND_ABORT("unsupported register class"); diff --git a/src/native/external/llvm-libunwind/src/Unwind-seh.cpp b/src/native/external/llvm-libunwind/src/Unwind-seh.cpp index b2bb119ed6d299..0b1930b44d1c64 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-seh.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-seh.cpp @@ -51,6 +51,32 @@ static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor); static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +// Local redefinition of this type; mingw-w64 headers lack the +// DISPATCHER_CONTEXT_NONVOLREG_ARM64 type as of May 2025, so locally redefine +// it and use that definition, to avoid needing to test/guess whether the real +// type is available of not. +union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 { + BYTE Buffer[11 * sizeof(DWORD64) + 8 * sizeof(double)]; + + struct { + DWORD64 GpNvRegs[11]; + double FpNvRegs[8]; + }; +}; + +// Custom data type definition; this type is not defined in WinSDK. +union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM { + BYTE Buffer[8 * sizeof(DWORD) + 8 * sizeof(double)]; + + struct { + DWORD GpNvRegs[8]; + double FpNvRegs[8]; + }; +}; +#pragma clang diagnostic pop + /// Common implementation of SEH-style handler functions used by Itanium- /// style frames. Depending on how and why it was called, it may do one of: /// a) Delegate to the given Itanium-style personality function; or @@ -137,7 +163,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, // If we were called by __libunwind_seh_personality(), indicate that // a handler was found; otherwise, initiate phase 2 by unwinding. if (ours && ms_exc->NumberParameters > 1) - return 4 /* ExceptionExecuteHandler in mingw */; + return static_cast(4); // This should never happen in phase 2. if (IS_UNWINDING(ms_exc->ExceptionFlags)) _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); @@ -148,14 +174,15 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, } // FIXME: Indicate target frame in foreign case! // phase 2: the clean up phase - RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable); + RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, disp->ContextRecord, + disp->HistoryTable); _LIBUNWIND_ABORT("RtlUnwindEx() failed"); case _URC_INSTALL_CONTEXT: { // If we were called by __libunwind_seh_personality(), indicate that // a handler was found; otherwise, it's time to initiate a collided // unwind to the target. if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) - return 4 /* ExceptionExecuteHandler in mingw */; + return static_cast(4); // This should never happen in phase 1. if (!IS_UNWINDING(ms_exc->ExceptionFlags)) _LIBUNWIND_ABORT("Personality installed context during phase 1!"); @@ -212,18 +239,32 @@ __libunwind_seh_personality(int version, _Unwind_Action state, ms_exc.ExceptionInformation[2] = state; DISPATCHER_CONTEXT *disp_ctx = __unw_seh_get_disp_ctx((unw_cursor_t *)context); +#if defined(__aarch64__) + LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol; + memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->X19, + sizeof(nonvol.GpNvRegs)); + for (int i = 0; i < 8; i++) + nonvol.FpNvRegs[i] = disp_ctx->ContextRecord->V[i + 8].D[0]; + disp_ctx->NonVolatileRegisters = nonvol.Buffer; +#elif defined(__arm__) + LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol; + memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->R4, + sizeof(nonvol.GpNvRegs)); + memcpy(&nonvol.FpNvRegs, &disp_ctx->ContextRecord->D[8], + sizeof(nonvol.FpNvRegs)); + disp_ctx->NonVolatileRegisters = nonvol.Buffer; +#endif _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling " "LanguageHandler %p(%p, %p, %p, %p)", (void *)disp_ctx->LanguageHandler, (void *)&ms_exc, (void *)disp_ctx->EstablisherFrame, (void *)disp_ctx->ContextRecord, (void *)disp_ctx); - EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc, - (PVOID)disp_ctx->EstablisherFrame, - disp_ctx->ContextRecord, - disp_ctx); + int ms_act = static_cast( + disp_ctx->LanguageHandler(&ms_exc, (PVOID)disp_ctx->EstablisherFrame, + disp_ctx->ContextRecord, disp_ctx)); _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler " "returned %d", - (int)ms_act); + ms_act); switch (ms_act) { case ExceptionContinueExecution: return _URC_END_OF_STACK; case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; diff --git a/src/native/external/llvm-libunwind/src/Unwind-wasm.c b/src/native/external/llvm-libunwind/src/Unwind-wasm.c index b18b32c5d17847..b0d6cd2d00fc59 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-wasm.c +++ b/src/native/external/llvm-libunwind/src/Unwind-wasm.c @@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext { // function thread_local struct _Unwind_LandingPadContext __wasm_lpad_context; -/// Calls to this function is in landing pads in compiler-generated user code. +/// Calls to this function are in landing pads in compiler-generated user code. /// In other EH schemes, stack unwinding is done by libunwind library, which -/// calls the personality function for each each frame it lands. On the other -/// hand, WebAssembly stack unwinding process is performed by a VM, and the -/// personality function cannot be called from there. So the compiler inserts -/// a call to this function in landing pads in the user code, which in turn -/// calls the personality function. +/// calls the personality function for each frame it lands. On the other hand, +/// WebAssembly stack unwinding process is performed by a VM, and the +/// personality function cannot be called from there. So the compiler inserts a +/// call to this function in landing pads in the user code, which in turn calls +/// the personality function. _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { struct _Unwind_Exception *exception_object = (struct _Unwind_Exception *)exception_ptr; @@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, /// Called by personality handler to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { - // The result will be used as an 1-based index after decrementing 1, so we + // The result will be used as a 1-based index after decrementing 1, so we // increment 2 here uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2; @@ -102,8 +102,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { } /// Not used in Wasm. -_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, - uintptr_t value) {} +_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t) {} /// Called by personality handler to get LSDA for current frame. _LIBUNWIND_EXPORT uintptr_t @@ -115,8 +114,7 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { } /// Not used in Wasm. -_LIBUNWIND_EXPORT uintptr_t -_Unwind_GetRegionStart(struct _Unwind_Context *context) { +_LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *) { return 0; } diff --git a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp index 1b1f032baf22fd..5838dbcaa9980a 100644 --- a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp +++ b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp @@ -11,7 +11,7 @@ #ifndef __UNWINDCURSOR_HPP__ #define __UNWINDCURSOR_HPP__ -#include "cet_unwind.h" +#include "shadow_stack_unwind.h" #include #include #include @@ -31,8 +31,9 @@ #endif #if defined(_LIBUNWIND_TARGET_LINUX) && \ - (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \ - defined(_LIBUNWIND_TARGET_S390X)) + (defined(_LIBUNWIND_TARGET_AARCH64) || \ + defined(_LIBUNWIND_TARGET_LOONGARCH) || \ + defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X)) #include #include #include @@ -40,6 +41,13 @@ #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 #endif +#if defined(_LIBUNWIND_TARGET_HAIKU) && \ + (defined(_LIBUNWIND_TARGET_I386) || defined(_LIBUNWIND_TARGET_X86_64)) +#include +#include +#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 +#endif + #include "AddressSpace.hpp" #include "CompactUnwinder.hpp" #include "config.h" @@ -82,6 +90,22 @@ struct UNWIND_INFO { uint16_t UnwindCodes[2]; }; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +union UNWIND_INFO_ARM { + DWORD HeaderData; + struct { + DWORD FunctionLength : 18; + DWORD Version : 2; + DWORD ExceptionDataPresent : 1; + DWORD EpilogInHeader : 1; + DWORD FunctionFragment : 1; + DWORD EpilogCount : 5; + DWORD CodeWords : 4; + }; +}; +#pragma clang diagnostic pop + extern "C" _Unwind_Reason_Code __libunwind_seh_personality( int, _Unwind_Action, uint64_t, _Unwind_Exception *, struct _Unwind_Context *); @@ -97,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache { typedef typename A::pint_t pint_t; public: static constexpr pint_t kSearchAll = static_cast(-1); - static pint_t findFDE(pint_t mh, pint_t pc); + template + static pint_t findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc); + static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); static void removeAllIn(pint_t mh); static void iterateCacheEntries(void (*func)(unw_word_t ip_start, @@ -150,7 +176,9 @@ bool DwarfFDECache::_registeredForDyldUnloads = false; #endif template -typename A::pint_t DwarfFDECache::findFDE(pint_t mh, pint_t pc) { +template +typename DwarfFDECache::pint_t +DwarfFDECache::findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc) { pint_t result = 0; _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { @@ -432,12 +460,9 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { virtual ~AbstractUnwindCursor() {} virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } - virtual void setReg(int, unw_word_t, unw_word_t) { + virtual void setReg(int, unw_word_t) { _LIBUNWIND_ABORT("setReg not implemented"); } - virtual unw_word_t getRegLocation(int) { - _LIBUNWIND_ABORT("getRegLocation not implemented"); - } virtual bool validFloatReg(int) { _LIBUNWIND_ABORT("validFloatReg not implemented"); } @@ -451,7 +476,9 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { virtual void getInfo(unw_proc_info_t *) { _LIBUNWIND_ABORT("getInfo not implemented"); } - virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } + _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() { + _LIBUNWIND_ABORT("jumpto not implemented"); + } virtual bool isSignalFrame() { _LIBUNWIND_ABORT("isSignalFrame not implemented"); } @@ -468,6 +495,12 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } #endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT + virtual void setWalkedFrames(unsigned) { + _LIBUNWIND_ABORT("setWalkedFrames not implemented"); + } +#endif + #ifdef _AIX virtual uintptr_t getDataRelBase() { _LIBUNWIND_ABORT("getDataRelBase not implemented"); @@ -933,20 +966,19 @@ template class UnwindCursor : public AbstractUnwindCursor{ typedef typename A::pint_t pint_t; public: - UnwindCursor(A &as); UnwindCursor(unw_context_t *context, A &as); UnwindCursor(A &as, void *threadArg); virtual ~UnwindCursor() {} virtual bool validReg(int); virtual unw_word_t getReg(int); - virtual void setReg(int, unw_word_t, unw_word_t); - virtual unw_word_t getRegLocation(int); + virtual void setReg(int, unw_word_t); virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); virtual int step(bool stage2 = false); virtual void getInfo(unw_proc_info_t *); - virtual void jumpto(); + _LIBUNWIND_TRACE_NO_INLINE + virtual void jumpto(); virtual bool isSignalFrame(); virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); @@ -955,6 +987,10 @@ class UnwindCursor : public AbstractUnwindCursor{ virtual void saveVFPAsX(); #endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT + virtual void setWalkedFrames(unsigned); +#endif + #ifdef _AIX virtual uintptr_t getDataRelBase(); #endif @@ -970,7 +1006,6 @@ class UnwindCursor : public AbstractUnwindCursor{ private: #if defined(_LIBUNWIND_ARM_EHABI) -public: bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); int stepWithEHABI() { @@ -1002,6 +1037,10 @@ class UnwindCursor : public AbstractUnwindCursor{ bool setInfoForSigReturn(Registers_arm64 &); int stepThroughSigReturn(Registers_arm64 &); #endif +#if defined(_LIBUNWIND_TARGET_LOONGARCH) + bool setInfoForSigReturn(Registers_loongarch &); + int stepThroughSigReturn(Registers_loongarch &); +#endif #if defined(_LIBUNWIND_TARGET_RISCV) bool setInfoForSigReturn(Registers_riscv &); int stepThroughSigReturn(Registers_riscv &); @@ -1016,7 +1055,7 @@ class UnwindCursor : public AbstractUnwindCursor{ template int stepThroughSigReturn(Registers &) { return UNW_STEP_END; } -#elif defined(_LIBUNWIND_TARGET_HAIKU) +#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) bool setInfoForSigReturn(); int stepThroughSigReturn(); #endif @@ -1024,21 +1063,28 @@ class UnwindCursor : public AbstractUnwindCursor{ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) bool getInfoFromFdeCie(const typename CFI_Parser::FDE_Info &fdeInfo, const typename CFI_Parser::CIE_Info &cieInfo, - pint_t pc, uintptr_t dso_base); - -public: - bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint=0); + typename R::link_hardened_reg_arg_t pc, + uintptr_t dso_base); + bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc, + const UnwindInfoSections §s, + uint32_t fdeSectionOffsetHint = 0); int stepWithDwarfFDE(bool stage2) { +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + typename R::reg_t rawPC = this->getReg(UNW_REG_IP); + typename R::link_reg_t pc; + _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); +#else + typename R::link_reg_t pc = this->getReg(UNW_REG_IP); +#endif return DwarfInstructions::stepWithDwarf( - _addressSpace, (pint_t)this->getReg(UNW_REG_IP), - (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2); + _addressSpace, pc, (pint_t)_info.unwind_info, _registers, + _isSignalFrame, stage2); } #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - bool getInfoFromCompactEncodingSection(pint_t pc, - const UnwindInfoSections §s); + bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc, + const UnwindInfoSections §s); int stepWithCompactEncoding(bool stage2 = false) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) if ( compactSaysUseDwarf() ) @@ -1325,18 +1371,14 @@ class UnwindCursor : public AbstractUnwindCursor{ bool _unwindInfoMissing; bool _isSignalFrame; #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ - defined(_LIBUNWIND_TARGET_HAIKU) + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) bool _isSigReturn = false; #endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT + uint32_t _walkedFrames; +#endif }; -template -UnwindCursor::UnwindCursor(A &as) - : _addressSpace(as) - , _unwindInfoMissing(false) - , _isSignalFrame(false) { - memset(&_info, 0, sizeof(_info)); -} template UnwindCursor::UnwindCursor(unw_context_t *context, A &as) @@ -1346,15 +1388,13 @@ UnwindCursor::UnwindCursor(unw_context_t *context, A &as) "UnwindCursor<> does not fit in unw_cursor_t"); static_assert((alignof(UnwindCursor) <= alignof(unw_cursor_t)), "UnwindCursor<> requires more alignment than unw_cursor_t"); - memset(&_info, 0, sizeof(_info)); + memset(static_cast(&_info), 0, sizeof(_info)); } template -UnwindCursor::UnwindCursor(A &as, void *arg) - : _addressSpace(as),_registers(arg), _unwindInfoMissing(false), - _isSignalFrame(false) { - memset(&_info, 0, sizeof(_info)); - +UnwindCursor::UnwindCursor(A &as, void *) + : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { + memset(static_cast(&_info), 0, sizeof(_info)); // FIXME // fill in _registers from thread arg } @@ -1371,13 +1411,8 @@ unw_word_t UnwindCursor::getReg(int regNum) { } template -void UnwindCursor::setReg(int regNum, unw_word_t value, unw_word_t location) { - _registers.setRegister(regNum, (typename A::pint_t)value, (typename A::pint_t)location); -} - -template -unw_word_t UnwindCursor::getRegLocation(int regNum) { - return _registers.getRegisterLocation(regNum); +void UnwindCursor::setReg(int regNum, unw_word_t value) { + _registers.setRegister(regNum, (typename A::pint_t)value); } template @@ -1396,7 +1431,46 @@ void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { } template void UnwindCursor::jumpto() { +#ifdef _LIBUNWIND_TRACE_RET_INJECT + /* + + The value of `_walkedFrames` is computed in `unwind_phase2` and represents the + number of frames walked starting `unwind_phase2` to get to the landing pad. + + ``` + // uc is initialized by __unw_getcontext in the parent frame. + // The first stack frame walked is unwind_phase2. + unsigned framesWalked = 1; + ``` + + To that, we need to add the number of function calls in libunwind between + `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long + jump, to rebalance the execution flow. + + ``` + frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646 + frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3 + frame #2: libunwind.1.dylib`libunwind::UnwindCursor::jumpto at UnwindCursor.hpp:1474:14 + frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7 + frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10 + frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9 + frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10 + frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5 + ... + ``` + + If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see + there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of + them will never return, since `__libunwind_Registers_arm64_jumpto` returns + back to the landing pad, so we need to subtract 1 to the number of + `_EXTRA_LIBUNWIND_FRAMES_WALKED`. + */ + + static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1; + _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED); +#else _registers.jumpto(); +#endif } #ifdef __arm__ @@ -1405,6 +1479,13 @@ template void UnwindCursor::saveVFPAsX() { } #endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT +template +void UnwindCursor::setWalkedFrames(unsigned walkedFrames) { + _walkedFrames = walkedFrames; +} +#endif + #ifdef _AIX template uintptr_t UnwindCursor::getDataRelBase() { @@ -1653,11 +1734,11 @@ bool UnwindCursor::getInfoFromEHABISection( template bool UnwindCursor::getInfoFromFdeCie( const typename CFI_Parser::FDE_Info &fdeInfo, - const typename CFI_Parser::CIE_Info &cieInfo, pint_t pc, - uintptr_t dso_base) { + const typename CFI_Parser::CIE_Info &cieInfo, + typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) { typename CFI_Parser::PrologInfo prolog; - if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, - R::getArch(), &prolog)) { + if (CFI_Parser::template parseFDEInstructions( + _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // Save off parsed FDE info _info.start_ip = fdeInfo.pcStart; _info.end_ip = fdeInfo.pcEnd; @@ -1677,46 +1758,42 @@ bool UnwindCursor::getInfoFromFdeCie( } template -bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, - const UnwindInfoSections §s, - uint32_t fdeSectionOffsetHint) { +bool UnwindCursor::getInfoFromDwarfSection( + typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s, + uint32_t fdeSectionOffsetHint) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; bool foundFDE = false; bool foundInCache = false; - // If compact encoding table gave offset into dwarf section, go directly there if (fdeSectionOffsetHint != 0) { - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, - sects.dwarf_section + fdeSectionOffsetHint, - &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, + sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); } - #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (!foundFDE && (sects.dwarf_index_section != 0)) { - foundFDE = EHHeaderParser::findFDE( + foundFDE = EHHeaderParser::template findFDE( _addressSpace, pc, sects.dwarf_index_section, (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); } #endif - if (!foundFDE) { // otherwise, search cache of previously found FDEs. - pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); + pint_t cachedFDE = + DwarfFDECache::template findFDE(sects.dso_base, pc); if (cachedFDE != 0) { - foundFDE = - CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, - cachedFDE, &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, + cachedFDE, &fdeInfo, &cieInfo); foundInCache = foundFDE; } } if (!foundFDE) { // Still not found, do full scan of __eh_frame section. - foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, - sects.dwarf_section_length, 0, - &fdeInfo, &cieInfo); + foundFDE = CFI_Parser::template findFDE( + _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0, + &fdeInfo, &cieInfo); } if (foundFDE) { if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { @@ -1740,8 +1817,8 @@ bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template -bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, - const UnwindInfoSections §s) { +bool UnwindCursor::getInfoFromCompactEncodingSection( + typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s) { const bool log = false; if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", @@ -1972,6 +2049,16 @@ bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, personalityIndex * sizeof(uint32_t)); pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; personality = _addressSpace.getP(personalityPointer); +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // The GOT for the personality function was signed address authenticated. + // Resign it as a regular function pointer. + const auto discriminator = ptrauth_blend_discriminator( + &_info.handler, __ptrauth_unwind_upi_handler_disc); + void *signedPtr = ptrauth_auth_and_resign( + (void *)personality, ptrauth_key_function_pointer, personalityPointer, + ptrauth_key_function_pointer, discriminator); + personality = (__typeof(personality))signedPtr; +#endif if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " "personalityDelta=0x%08X, personality=0x%08llX\n", @@ -1985,7 +2072,11 @@ bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, _info.start_ip = funcStart; _info.end_ip = funcEnd; _info.lsda = lsda; - _info.handler = personality; + // We use memmove to copy the personality function as we have already manually + // re-signed the pointer, and assigning directly will attempt to incorrectly + // sign the already signed value. + memmove(reinterpret_cast(&_info.handler), + reinterpret_cast(&personality), sizeof(personality)); _info.gp = 0; _info.flags = 0; _info.format = encoding; @@ -2038,6 +2129,61 @@ bool UnwindCursor::getInfoFromSEH(pint_t pc) { _info.handler = 0; } } +#elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM) + +#if defined(_LIBUNWIND_TARGET_AARCH64) +#define FUNC_LENGTH_UNIT 4 +#define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA +#else +#define FUNC_LENGTH_UNIT 2 +#define XDATA_TYPE UNWIND_INFO_ARM +#endif + if (unwindEntry->Flag != 0) { // Packed unwind info + _info.end_ip = + _info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT; + // Only fill in the handler and LSDA if they're stale. + if (pc != getLastPC()) { + // Packed unwind info doesn't have an exception handler. + _info.lsda = 0; + _info.handler = 0; + } + } else { + XDATA_TYPE *xdata = + reinterpret_cast(base + unwindEntry->UnwindData); + _info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT; + // Only fill in the handler and LSDA if they're stale. + if (pc != getLastPC()) { + if (xdata->ExceptionDataPresent) { + uint32_t offset = 1; // The main xdata + uint32_t codeWords = xdata->CodeWords; + uint32_t epilogScopes = xdata->EpilogCount; + if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) { + // The extension word has got the same layout for both ARM and ARM64 + uint32_t extensionWord = reinterpret_cast(xdata)[1]; + codeWords = (extensionWord >> 16) & 0xff; + epilogScopes = extensionWord & 0xffff; + offset++; + } + if (!xdata->EpilogInHeader) + offset += epilogScopes; + offset += codeWords; + uint32_t *exceptionHandlerInfo = + reinterpret_cast(xdata) + offset; + _dispContext.HandlerData = &exceptionHandlerInfo[1]; + _dispContext.LanguageHandler = reinterpret_cast( + base + exceptionHandlerInfo[0]); + _info.lsda = reinterpret_cast(_dispContext.HandlerData); + if (exceptionHandlerInfo[0]) + _info.handler = + reinterpret_cast(__libunwind_seh_personality); + else + _info.handler = 0; + } else { + _info.lsda = 0; + _info.handler = 0; + } + } + } #endif setLastPC(pc); return true; @@ -2579,15 +2725,23 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, template void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ - defined(_LIBUNWIND_TARGET_HAIKU) + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) _isSigReturn = false; #endif - pint_t pc = static_cast(this->getReg(UNW_REG_IP)); + typename R::reg_t rawPC = this->getReg(UNW_REG_IP); + #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; + rawPC &= (pint_t)~0x1; +#endif + + typename R::link_reg_t pc; +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); +#else + pc = rawPC; #endif // Exit early if at the top of the stack. @@ -2622,7 +2776,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; - if (_addressSpace.findUnwindSections(pc, sects)) { + if (_addressSpace.template findUnwindSections(pc, sects)) { #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { @@ -2678,8 +2832,8 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #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::findFDE(DwarfFDECache::kSearchAll, - pc); + pint_t cachedFDE = + DwarfFDECache::template findFDE(DwarfFDECache::kSearchAll, pc); if (cachedFDE != 0) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; @@ -2691,7 +2845,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { // Lastly, ask AddressSpace object about platform specific ways to locate // other FDEs. pint_t fde; - if (_addressSpace.findOtherFDE(pc, fde)) { + if (_addressSpace.template findOtherFDE(pc, fde)) { typename CFI_Parser::FDE_Info fdeInfo; typename CFI_Parser::CIE_Info cieInfo; if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { @@ -2704,7 +2858,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ - defined(_LIBUNWIND_TARGET_HAIKU) + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) if (setInfoForSigReturn()) return; #endif @@ -2715,6 +2869,21 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ defined(_LIBUNWIND_TARGET_AARCH64) + +/* + * The linux sigreturn restorer stub will always have the form: + * + * d2801168 movz x8, #0x8b + * d4000001 svc #0x0 + */ +#if defined(__AARCH64EB__) +#define MOVZ_X8_8B 0x681180d2 +#define SVC_0 0x010000d4 +#else +#define MOVZ_X8_8B 0xd2801168 +#define SVC_0 0xd4000001 +#endif + template bool UnwindCursor::setInfoForSigReturn(Registers_arm64 &) { // Look for the sigreturn trampoline. The trampoline's body is two @@ -2739,7 +2908,7 @@ bool UnwindCursor::setInfoForSigReturn(Registers_arm64 &) { return false; auto *instructions = reinterpret_cast(pc); // Look for instructions: mov x8, #0x8b; svc #0x0 - if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001) + if (instructions[0] != MOVZ_X8_8B || instructions[1] != SVC_0) return false; _info = {}; @@ -2773,72 +2942,70 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { for (int i = 0; i <= 30; ++i) { uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs + static_cast(i * 8)); - _registers.setRegister(UNW_AARCH64_X0 + i, value, 0); + _registers.setRegister(UNW_AARCH64_X0 + i, value); } - _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp), 0); - _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc), 0); + _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp)); + _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc)); _isSignalFrame = true; return UNW_STEP_SUCCESS; } +#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && + // defined(_LIBUNWIND_TARGET_AARCH64) -#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) -#include -#include +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ + defined(_LIBUNWIND_TARGET_LOONGARCH) +template +bool UnwindCursor::setInfoForSigReturn(Registers_loongarch &) { + const pint_t pc = static_cast(getReg(UNW_REG_IP)); + // The PC might contain an invalid address if the unwind info is bad, so + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + const auto *instructions = reinterpret_cast(pc); + // Look for the two instructions used in the sigreturn trampoline + // __vdso_rt_sigreturn: + // + // 0x03822c0b li a7,0x8b + // 0x002b0000 syscall 0 + if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000) + return false; -extern "C" { -extern void *__gCommPageAddress; + _info = {}; + _info.start_ip = pc; + _info.end_ip = pc + 4; + _isSigReturn = true; + return true; } template -bool UnwindCursor::setInfoForSigReturn() { -#if defined(_LIBUNWIND_TARGET_X86_64) - addr_t signal_handler = - (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + - (addr_t)__gCommPageAddress); - addr_t signal_handler_ret = signal_handler + 45; -#endif - pint_t pc = static_cast(this->getReg(UNW_REG_IP)); - if (pc == signal_handler_ret) { - _info = {}; - _info.start_ip = signal_handler; - _info.end_ip = signal_handler_ret; - _isSigReturn = true; - return true; - } - return false; -} +int UnwindCursor::stepThroughSigReturn(Registers_loongarch &) { + // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: + // - 128-byte siginfo struct + // - ucontext_t struct: + // - 8-byte long (__uc_flags) + // - 8-byte pointer (*uc_link) + // - 24-byte uc_stack + // - 8-byte uc_sigmask + // - 120-byte of padding to allow sigset_t to be expanded in the future + // - 8 bytes of padding because sigcontext has 16-byte alignment + // - struct sigcontext uc_mcontext + // [1] + // https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c + const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; -template -int UnwindCursor::stepThroughSigReturn() { + const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; + _registers.setIP(_addressSpace.get64(sigctx)); + for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) { + // skip R0 + uint64_t value = + _addressSpace.get64(sigctx + static_cast((i + 1) * 8)); + _registers.setRegister(i, value); + } _isSignalFrame = true; - pint_t sp = _registers.getSP(); -#if defined(_LIBUNWIND_TARGET_X86_64) - vregs *regs = (vregs *)(sp + 0x70); - - _registers.setRegister(UNW_REG_IP, regs->rip); - _registers.setRegister(UNW_REG_SP, regs->rsp); - _registers.setRegister(UNW_X86_64_RAX, regs->rax); - _registers.setRegister(UNW_X86_64_RDX, regs->rdx); - _registers.setRegister(UNW_X86_64_RCX, regs->rcx); - _registers.setRegister(UNW_X86_64_RBX, regs->rbx); - _registers.setRegister(UNW_X86_64_RSI, regs->rsi); - _registers.setRegister(UNW_X86_64_RDI, regs->rdi); - _registers.setRegister(UNW_X86_64_RBP, regs->rbp); - _registers.setRegister(UNW_X86_64_R8, regs->r8); - _registers.setRegister(UNW_X86_64_R9, regs->r9); - _registers.setRegister(UNW_X86_64_R10, regs->r10); - _registers.setRegister(UNW_X86_64_R11, regs->r11); - _registers.setRegister(UNW_X86_64_R12, regs->r12); - _registers.setRegister(UNW_X86_64_R13, regs->r13); - _registers.setRegister(UNW_X86_64_R14, regs->r14); - _registers.setRegister(UNW_X86_64_R15, regs->r15); - // TODO: XMM -#endif - return UNW_STEP_SUCCESS; } #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && - // defined(_LIBUNWIND_TARGET_AARCH64) + // defined(_LIBUNWIND_TARGET_LOONGARCH) #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ defined(_LIBUNWIND_TARGET_RISCV) @@ -2882,10 +3049,10 @@ int UnwindCursor::stepThroughSigReturn(Registers_riscv &) { const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; - _registers.setIP(_addressSpace.get64(sigctx), 0); + _registers.setIP(_addressSpace.get64(sigctx)); for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) { uint64_t value = _addressSpace.get64(sigctx + static_cast(i * 8)); - _registers.setRegister(i, value, 0); + _registers.setRegister(i, value); } _isSignalFrame = true; return UNW_STEP_SUCCESS; @@ -2997,6 +3164,96 @@ int UnwindCursor::stepThroughSigReturn(Registers_s390x &) { #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && // defined(_LIBUNWIND_TARGET_S390X) +#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) +template +bool UnwindCursor::setInfoForSigReturn() { + Dl_info dlinfo; + const auto isSignalHandler = [&](pint_t addr) { + if (!dladdr(reinterpret_cast(addr), &dlinfo)) + return false; + if (strcmp(dlinfo.dli_fname, "commpage")) + return false; + if (dlinfo.dli_sname == NULL || + strcmp(dlinfo.dli_sname, "commpage_signal_handler")) + return false; + return true; + }; + + pint_t pc = static_cast(this->getReg(UNW_REG_IP)); + if (!isSignalHandler(pc)) + return false; + + pint_t start = reinterpret_cast(dlinfo.dli_saddr); + + static size_t signalHandlerSize = 0; + if (signalHandlerSize == 0) { + size_t boundLow = 0; + size_t boundHigh = static_cast(-1); + + area_info areaInfo; + if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK) + boundHigh = areaInfo.size; + + while (boundLow < boundHigh) { + size_t boundMid = boundLow + ((boundHigh - boundLow) / 2); + pint_t test = start + boundMid; + if (test >= start && isSignalHandler(test)) + boundLow = boundMid + 1; + else + boundHigh = boundMid; + } + + signalHandlerSize = boundHigh; + } + + _info = {}; + _info.start_ip = start; + _info.end_ip = start + signalHandlerSize; + _isSigReturn = true; + + return true; +} + +template +int UnwindCursor::stepThroughSigReturn() { + _isSignalFrame = true; + +#if defined(_LIBUNWIND_TARGET_X86_64) + // Layout of the stack before function call: + // - signal_frame_data + // + siginfo_t (public struct, fairly stable) + // + ucontext_t (public struct, fairly stable) + // - mcontext_t -> Offset 0x70, this is what we want. + // - frame->ip (8 bytes) + // - frame->bp (8 bytes). Not written by the kernel, + // but the signal handler has a "push %rbp" instruction. + pint_t bp = this->getReg(UNW_X86_64_RBP); + vregs *regs = (vregs *)(bp + 0x70); + + _registers.setRegister(UNW_REG_IP, regs->rip); + _registers.setRegister(UNW_REG_SP, regs->rsp); + _registers.setRegister(UNW_X86_64_RAX, regs->rax); + _registers.setRegister(UNW_X86_64_RDX, regs->rdx); + _registers.setRegister(UNW_X86_64_RCX, regs->rcx); + _registers.setRegister(UNW_X86_64_RBX, regs->rbx); + _registers.setRegister(UNW_X86_64_RSI, regs->rsi); + _registers.setRegister(UNW_X86_64_RDI, regs->rdi); + _registers.setRegister(UNW_X86_64_RBP, regs->rbp); + _registers.setRegister(UNW_X86_64_R8, regs->r8); + _registers.setRegister(UNW_X86_64_R9, regs->r9); + _registers.setRegister(UNW_X86_64_R10, regs->r10); + _registers.setRegister(UNW_X86_64_R11, regs->r11); + _registers.setRegister(UNW_X86_64_R12, regs->r12); + _registers.setRegister(UNW_X86_64_R13, regs->r13); + _registers.setRegister(UNW_X86_64_R14, regs->r14); + _registers.setRegister(UNW_X86_64_R15, regs->r15); + // TODO: XMM +#endif // defined(_LIBUNWIND_TARGET_X86_64) + + return UNW_STEP_SUCCESS; +} +#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) + template int UnwindCursor::step(bool stage2) { (void)stage2; // Bottom of stack is defined is when unwind info cannot be found. @@ -3006,7 +3263,7 @@ template int UnwindCursor::step(bool stage2) { // Use unwinding info to modify register set as if function returned. int result; #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ - defined(_LIBUNWIND_TARGET_HAIKU) + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) if (_isSigReturn) { result = this->stepThroughSigReturn(); } else @@ -3043,16 +3300,22 @@ template int UnwindCursor::step(bool stage2) { template void UnwindCursor::getInfo(unw_proc_info_t *info) { if (_unwindInfoMissing) - memset(info, 0, sizeof(*info)); + memset(static_cast(info), 0, sizeof(*info)); else *info = _info; } template bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, - unw_word_t *offset) { - return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), - buf, bufLen, offset); + unw_word_t *offset) { +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + typename R::reg_t rawPC = this->getReg(UNW_REG_IP); + typename R::link_reg_t pc; + _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); +#else + typename R::link_reg_t pc = this->getReg(UNW_REG_IP); +#endif + return _addressSpace.template findFunctionName(pc, buf, bufLen, offset); } #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) @@ -3087,7 +3350,7 @@ bool UnwindCursor::isReadableAddr(const pint_t addr) const { #endif #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) -extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { +extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) { AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->get_registers(); } diff --git a/src/native/external/llvm-libunwind/src/UnwindLevel1.c b/src/native/external/llvm-libunwind/src/UnwindLevel1.c index 7e785f4d31e716..7368b3cb803362 100644 --- a/src/native/external/llvm-libunwind/src/UnwindLevel1.c +++ b/src/native/external/llvm-libunwind/src/UnwindLevel1.c @@ -25,10 +25,10 @@ #include #include -#include "cet_unwind.h" #include "config.h" #include "libunwind.h" #include "libunwind_ext.h" +#include "shadow_stack_unwind.h" #include "unwind.h" #if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ @@ -36,57 +36,77 @@ #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND -// When CET is enabled, each "call" instruction will push return address to -// CET shadow stack, each "ret" instruction will pop current CET shadow stack -// top and compare it with target address which program will return. -// In exception handing, some stack frames will be skipped before jumping to -// landing pad and we must adjust CET shadow stack accordingly. -// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we -// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using -// a regular function call to avoid pushing to CET shadow stack again. +// When shadow stack is enabled, a separate stack containing only return +// addresses would be maintained. On function return, the return address would +// be compared to the popped address from shadow stack to ensure the return +// target is not tempered with. When unwinding, we're skipping the normal return +// procedure for multiple frames and thus need to pop the return addresses of +// the skipped frames from shadow stack to avoid triggering an exception (using +// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family +// CET, push the return adddresses onto shadow stack with common call +// instructions, so for these architectures, normal function calls should be +// avoided when invoking the `jumpto()` function. To do this, we use inline +// assemblies to "goto" the `jumpto()` for these architectures. #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) -#define __unw_phase2_resume(cursor, fn) \ +#define __unw_phase2_resume(cursor, payload) \ do { \ - (void)fn; \ - __unw_resume((cursor)); \ + __unw_resume_with_frames_walked((cursor), (payload)); \ } while (0) #elif defined(_LIBUNWIND_TARGET_I386) -#define __cet_ss_step_size 4 -#define __unw_phase2_resume(cursor, fn) \ +#define __shstk_step_size (4) +#define __unw_phase2_resume(cursor, payload) \ do { \ - _LIBUNWIND_POP_CET_SSP((fn)); \ - void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ - void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + _LIBUNWIND_POP_SHSTK_SSP((payload)); \ + void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ + void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ __asm__ volatile("push %%edi\n\t" \ "sub $4, %%esp\n\t" \ - "jmp *%%edx\n\t" :: "D"(cetRegContext), \ - "d"(cetJumpAddress)); \ + "jmp *%%edx\n\t" ::"D"(shstkRegContext), \ + "d"(shstkJumpAddress)); \ } while (0) #elif defined(_LIBUNWIND_TARGET_X86_64) -#define __cet_ss_step_size 8 -#define __unw_phase2_resume(cursor, fn) \ +#define __shstk_step_size (8) +#define __unw_phase2_resume(cursor, payload) \ do { \ - _LIBUNWIND_POP_CET_SSP((fn)); \ - void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ - void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ - __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ - "d"(cetJumpAddress)); \ + _LIBUNWIND_POP_SHSTK_SSP((payload)); \ + void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ + void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ + __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \ + "d"(shstkJumpAddress)); \ } while (0) #elif defined(_LIBUNWIND_TARGET_AARCH64) -#define __cet_ss_step_size 8 -#define __unw_phase2_resume(cursor, fn) \ +#define __shstk_step_size (8) +#define __unw_phase2_resume(cursor, payload) \ do { \ - _LIBUNWIND_POP_CET_SSP((fn)); \ - void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ - void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + _LIBUNWIND_POP_SHSTK_SSP((payload)); \ + void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ + void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ __asm__ volatile("mov x0, %0\n\t" \ + "mov x1, #0\n\t" \ "br %1\n\t" \ : \ - : "r"(cetRegContext), "r"(cetJumpAddress) \ - : "x0"); \ + : "r"(shstkRegContext), "r"(shstkJumpAddress) \ + : "x0", "x1"); \ } while (0) #endif +// We need this helper function as the semantics of casting between integers and +// function pointers mean that we end up with a function pointer without the +// correct signature. Instead we assign to an integer with a matching schema, +// and then memmove the result into a variable of the correct type. This memmove +// is possible as `_Unwind_Personality_Fn` is a standard function pointer, and +// as such is not address diversified. +static _Unwind_Personality_Fn get_handler_function(unw_proc_info_t *frameInfo) { + uintptr_t __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, + 0, + ptrauth_function_pointer_type_discriminator(_Unwind_Personality_Fn)) + reauthenticatedIntegerHandler = frameInfo->handler; + _Unwind_Personality_Fn handler; + memmove(&handler, (void *)&reauthenticatedIntegerHandler, + sizeof(_Unwind_Personality_Fn)); + return handler; +} + static _Unwind_Reason_Code unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { __unw_init_local(cursor, uc); @@ -144,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except // If there is a personality routine, ask it if it will want to stop at // this frame. if (frameInfo.handler != 0) { - _Unwind_Personality_Fn p = - (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); + _Unwind_Personality_Fn p = get_handler_function(&frameInfo); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_obj=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); @@ -181,14 +200,16 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except } return _URC_NO_REASON; } -extern int __unw_step_stage2(unw_cursor_t *); #if defined(_LIBUNWIND_USE_GCS) // Enable the GCS target feature to permit gcspop instructions to be used. -__attribute__((target("gcs"))) +__attribute__((target("+gcs"))) +#else +_LIBUNWIND_TRACE_NO_INLINE #endif static _Unwind_Reason_Code -unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { +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_obj=%p)", @@ -255,16 +276,16 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except } #endif -// In CET enabled environment, we check return address stored in normal stack -// against return address stored in CET shadow stack, if the 2 addresses don't +// In shadow stack enabled environment, we check return address stored in normal +// stack against return address stored in shadow stack, if the 2 addresses don't // match, it means return address in normal stack has been corrupted, we return // _URC_FATAL_PHASE2_ERROR. #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) if (shadowStackTop != 0) { unw_word_t retInNormalStack; __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); - unsigned long retInShadowStack = *( - unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked); + unsigned long retInShadowStack = + *(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked); if (retInNormalStack != retInShadowStack) return _URC_FATAL_PHASE2_ERROR; } @@ -272,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { - _Unwind_Personality_Fn p = - (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); + _Unwind_Personality_Fn p = get_handler_function(&frameInfo); _Unwind_Action action = _UA_CLEANUP_PHASE; if (sp == exception_object->private_2) { // Tell personality this was the frame it marked in phase 1. @@ -329,12 +349,14 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except #if defined(_LIBUNWIND_USE_GCS) // Enable the GCS target feature to permit gcspop instructions to be used. -__attribute__((target("gcs"))) +__attribute__((target("+gcs"))) +#else +_LIBUNWIND_TRACE_NO_INLINE #endif static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, - _Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) { + _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter) { __unw_init_local(cursor, uc); // uc is initialized by __unw_getcontext in the parent frame. The first stack @@ -390,8 +412,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { - _Unwind_Personality_Fn p = - (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); + _Unwind_Personality_Fn p = get_handler_function(&frameInfo); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2_forced(ex_obj=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); @@ -440,7 +461,6 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, return _URC_FATAL_PHASE2_ERROR; } - /// Called by __cxa_throw. Only returns if there is a fatal error. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { @@ -594,6 +614,18 @@ _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); + +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + // If we are in an arm64e frame, then the PC should have been signed with the + // sp + { + unw_word_t sp; + __unw_get_reg(cursor, UNW_REG_SP, &sp); + result = (unw_word_t)ptrauth_auth_data((void *)result, + ptrauth_key_return_address, sp); + } +#endif + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, (void *)context, result); return (uintptr_t)result; diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S index 1702d016c368ba..76a80344034f71 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersRestore.S @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#if !defined(__wasm__) + #include "assembly.h" #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 @@ -16,13 +18,17 @@ #if defined(_AIX) .toc +#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE) + .section .text,"axy",@progbits,unique,0 #else .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) #if defined(__i386__) +.att_syntax + DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # # extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); @@ -66,7 +72,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # skip fs # skip gs -#elif defined(__x86_64__) +#elif defined(__x86_64__) && !defined(__arm64ec__) +.att_syntax DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) # @@ -629,18 +636,35 @@ Lnovec: #elif defined(__aarch64__) +#ifndef __has_feature +#define __has_feature(__feature) 0 +#endif + #if defined(__ARM_FEATURE_GCS_DEFAULT) .arch_extension gcs #endif // -// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); +// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned); // // On entry: // thread_state pointer is in x0 +// walked_frames counter is in x1 // .p2align 2 DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) + + #if defined(_LIBUNWIND_TRACE_RET_INJECT) + cbz w1, 1f + 0: + subs w1, w1, #1 + adr x16, #8 + ret x16 + + b.ne 0b + 1: + #endif + // skip restore of x0,x1 for now ldp x2, x3, [x0, #0x010] ldp x4, x5, [x0, #0x020] @@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) ldp x24,x25, [x0, #0x0C0] ldp x26,x27, [x0, #0x0D0] ldp x28,x29, [x0, #0x0E0] - ldr x30, [x0, #0x100] // restore pc into lr + #if defined(__ARM_FP) && __ARM_FP != 0 ldp d0, d1, [x0, #0x110] ldp d2, d3, [x0, #0x120] @@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) // context struct, because it is allocated on the stack, and an exception // could clobber the de-allocated portion of the stack after sp has been // restored. - ldr x16, [x0, #0x0F8] + + ldr x16, [x0, #0x0F8] // load sp into scratch + ldr lr, [x0, #0x100] // restore pc into lr + +#if __has_feature(ptrauth_calls) + // The LR is signed with its address inside the register state. Time + // to resign to be a regular ROP protected signed pointer + add x1, x0, #0x100 + autib lr, x1 + pacib lr, x16 // signed the scratch register for sp +#endif + ldp x0, x1, [x0, #0x000] // restore x0,x1 mov sp,x16 // restore sp #if defined(__ARM_FEATURE_GCS_DEFAULT) @@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) gcspushm x30 Lnogcs: #endif + +#if __has_feature(ptrauth_calls) + retab +#else ret x30 // jump to pc +#endif #elif defined(__arm__) && !defined(__APPLE__) @@ -1044,9 +1084,10 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) lw $27, (4 * 27)($4) lw $28, (4 * 28)($4) lw $29, (4 * 29)($4) - lw $30, (4 * 30)($4) // load new pc into ra lw $31, (4 * 32)($4) + // MIPS 1 has load delay slot. Ensure lw $31 and jr are separated by an instruction. + lw $30, (4 * 30)($4) // jump to ra, load a0 in the delay slot jr $31 lw $4, (4 * 4)($4) @@ -1082,11 +1123,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) ld $2, (8 * 2)($4) ld $3, (8 * 3)($4) // skip a0 for now - .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 + .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29 ld $\i, (8 * \i)($4) .endr // load new pc into ra ld $31, (8 * 32)($4) + // MIPS 1 has load delay slot. Ensure lw $31 and jr are separated by an instruction. + ld $30, (8 * 30)($4) // jump to ra, load a0 in the delay slot jr $31 ld $4, (8 * 4)($4) @@ -1250,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) #endif -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ NO_EXEC_STACK_DIRECTIVE +#endif /* !defined(__wasm__) */ diff --git a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S index a489a8ba6df159..f988fd461def17 100644 --- a/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S +++ b/src/native/external/llvm-libunwind/src/UnwindRegistersSave.S @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#if !defined(__wasm__) + #include "assembly.h" #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 @@ -16,13 +18,16 @@ #if defined(_AIX) .toc +#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE) + .section .text,"axy",@progbits,unique,0 #else .text #endif -#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) +#if !defined(__USING_SJLJ_EXCEPTIONS__) #if defined(__i386__) +.att_syntax # # extern int __unw_getcontext(unw_context_t* thread_state) @@ -65,7 +70,49 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) xorl %eax, %eax # return UNW_ESUCCESS ret +#elif defined(__arm64ec__) + +// +// extern int __unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in x0 +// + .section .text,"xr",discard,"#__unw_getcontext" + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext") + stp x8, x27, [x0, #0x000] // rax, rbx + stp x0, x1, [x0, #0x010] // rcx, rdx + stp x26,x25, [x0, #0x020] // rdi, rsi + mov x1, sp + stp fp, x1, [x0, #0x030] // rbp, rsp + stp x2, x3, [x0, #0x040] // r8, r9 + stp x4, x5, [x0, #0x050] // r10, r11 + stp x19,x20, [x0, #0x060] // r12, r13 + stp x21,x22, [x0, #0x070] // r14, r15 + str x30, [x0, #0x080] // store return address as pc + stp q0, q1, [x0, #0x0b0] // xmm0, xmm1 + stp q2, q3, [x0, #0x0d0] // xmm2, xmm3 + stp q4, q5, [x0, #0x0f0] // xmm4, xmm5 + stp q6, q7, [x0, #0x110] // xmm6, xmm7 + stp q8, q9, [x0, #0x130] // xmm8, xmm9 + stp q10,q11, [x0, #0x150] // xmm10,xmm11 + stp q12,q13, [x0, #0x170] // xmm12,xmm13 + stp q14,q15, [x0, #0x190] // xmm14,xmm15 + mov x0, #0 // return UNW_ESUCCESS + ret + + .weak_anti_dep __unw_getcontext + .set __unw_getcontext, "#__unw_getcontext" + + .section .hybmp$x,"yi" + .symidx "#__unw_getcontext" + .symidx $ientry_thunk$cdecl$i8$i8 + .word 1 + .text + #elif defined(__x86_64__) +.att_syntax # # extern int __unw_getcontext(unw_context_t* thread_state) @@ -718,6 +765,10 @@ LnoR2Fix: #elif defined(__aarch64__) +#ifndef __has_feature +#define __has_feature(__feature) 0 +#endif + // // extern int __unw_getcontext(unw_context_t* thread_state) // @@ -726,6 +777,11 @@ LnoR2Fix: // .p2align 2 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) + +#if __has_feature(ptrauth_calls) + pacibsp +#endif + stp x0, x1, [x0, #0x000] stp x2, x3, [x0, #0x010] stp x4, x5, [x0, #0x020] @@ -766,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) str d31, [x0, #0x208] #endif mov x0, #0 // return UNW_ESUCCESS + +#if __has_feature(ptrauth_calls) + retab +#else + ret +#endif + +// +// extern "C" int64_t __libunwind_Registers_arm64_za_disable() +// +// This function implements the requirements of the __arm_za_disable ABI +// routine, except that it will not abort; it will return a non-zero value +// to signify the routine failed. +// +// Note: This function uses SME instructions. It must only be called if SME +// has been confirmed to be available. +// +// On return: +// +// A status is placed in x0. A zero value indicates success; any non-zero +// value indicates failure. +// + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_za_disable) + .variant_pcs __libunwind_Registers_arm64_za_disable +#if __has_feature(ptrauth_calls) + pacibsp +#endif + // If TPIDR2_EL0 is null, the subroutine just disables ZA. + .inst 0xd53bd0b0 // mrs x16, TPIDR2_EL0 + cbz x16, 1f + + // If any of the reserved bytes in the first 16 bytes of the TPIDR2 block are + // nonzero, return a non-zero value (libunwind will then abort). + ldrh w0, [x16, #10] + cbnz w0, 2f + ldr w0, [x16, #12] + cbnz w0, 2f + + // If num_za_save_slices is zero, the subroutine just disables ZA. + ldrh w0, [x16, #8] + cbz x0, 1f + + // If za_save_buffer is NULL, the subroutine just disables ZA. + ldr x16, [x16] + cbz x16, 1f + + // Store ZA to za_save_buffer. + mov x15, xzr +0: + .inst 0xe1206200 // str za[w15,0], [x16] + .inst 0x04305830 // addsvl x16, x16, #1 + add x15, x15, #1 + cmp x0, x15 + b.ne 0b +1: + // * Set TPIDR2_EL0 to null. + .inst 0xd51bd0bf // msr TPIDR2_EL0, xzr + // * Set PSTATE.ZA to 0. + .inst 0xd503447f // smstop za + // * Return zero (success) + mov x0, xzr +2: +#if __has_feature(ptrauth_calls) + retab +#else ret +#endif #elif defined(__arm__) && !defined(__APPLE__) @@ -1181,8 +1304,18 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) #endif +#ifdef __arm64ec__ + .globl "#unw_getcontext" + .set "#unw_getcontext", "#__unw_getcontext" + .weak_anti_dep unw_getcontext + .set unw_getcontext, "#unw_getcontext" + EXPORT_SYMBOL(unw_getcontext) +#else WEAK_ALIAS(__unw_getcontext, unw_getcontext) +#endif -#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ +#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ NO_EXEC_STACK_DIRECTIVE + +#endif /* !defined(__wasm__) */ diff --git a/src/native/external/llvm-libunwind/src/Unwind_AIXExtras.cpp b/src/native/external/llvm-libunwind/src/Unwind_AIXExtras.cpp index 66194ab4a16ba2..97b6c3e5e01aea 100644 --- a/src/native/external/llvm-libunwind/src/Unwind_AIXExtras.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind_AIXExtras.cpp @@ -10,6 +10,7 @@ // This file is only used for AIX. #if defined(_AIX) +#include "AddressSpace.hpp" #include "config.h" #include "libunwind_ext.h" #include diff --git a/src/native/external/llvm-libunwind/src/assembly.h b/src/native/external/llvm-libunwind/src/assembly.h index f8e83e138eff50..84c9d526f1d759 100644 --- a/src/native/external/llvm-libunwind/src/assembly.h +++ b/src/native/external/llvm-libunwind/src/assembly.h @@ -15,7 +15,7 @@ #ifndef UNWIND_ASSEMBLY_H #define UNWIND_ASSEMBLY_H -#if defined(__linux__) && defined(__CET__) +#if defined(__CET__) #include #define _LIBUNWIND_CET_ENDBR _CET_ENDBR #else @@ -132,6 +132,10 @@ #if defined(__APPLE__) +#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__) +#define _LIBUNWIND_TRACE_RET_INJECT 1 +#endif + #define SYMBOL_IS_FUNC(name) #define HIDDEN_SYMBOL(name) .private_extern name #if defined(_LIBUNWIND_HIDE_SYMBOLS) diff --git a/src/native/external/llvm-libunwind/src/config.h b/src/native/external/llvm-libunwind/src/config.h index deb5a4d4d73d46..f017403fa2234f 100644 --- a/src/native/external/llvm-libunwind/src/config.h +++ b/src/native/external/llvm-libunwind/src/config.h @@ -28,6 +28,9 @@ #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 #endif + #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__) + #define _LIBUNWIND_TRACE_RET_INJECT 1 + #endif #elif defined(_WIN32) #ifdef __SEH__ #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 @@ -61,6 +64,12 @@ #endif #endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT +#define _LIBUNWIND_TRACE_NO_INLINE __attribute__((noinline, disable_tail_calls)) +#else +#define _LIBUNWIND_TRACE_NO_INLINE +#endif + #if defined(_LIBUNWIND_HIDE_SYMBOLS) // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility. #define _LIBUNWIND_EXPORT diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index fec5fe8799f91b..7ffffc2a30c0ae 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -111,21 +111,62 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg) /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t value, unw_word_t *pos) { + unw_word_t value) { _LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", static_cast(cursor), regNum, value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { - co->setReg(regNum, (pint_t)value, (pint_t)pos); // special case altering IP to re-find info (being called by personality // function) if (regNum == UNW_REG_IP) { unw_proc_info_t info; // First, get the FDE for the old location and then update it. co->getInfo(&info); - co->setInfoBasedOnIPRegister(false); + + pint_t sp = (pint_t)co->getReg(UNW_REG_SP); + +#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) + { + // It is only valid to set the IP within the current function. This is + // important for ptrauth, otherwise the IP cannot be correctly signed. + // The current signature of `value` is via the schema: + // __ptrauth(ptrauth_key_return_address, <>, 0) + // For this to be generally usable we manually re-sign it to the + // directly supported schema: + // __ptrauth(ptrauth_key_return_address, 1, 0) + unw_word_t + __unwind_ptrauth_restricted_intptr(ptrauth_key_return_address, 1, + 0) authenticated_value; + unw_word_t opaque_value = (uint64_t)ptrauth_auth_and_resign( + (void *)value, ptrauth_key_return_address, sp, + ptrauth_key_return_address, &authenticated_value); + memmove(reinterpret_cast(&authenticated_value), + reinterpret_cast(&opaque_value), + sizeof(authenticated_value)); + if (authenticated_value < info.start_ip || + authenticated_value > info.end_ip) + _LIBUNWIND_ABORT("PC vs frame info mismatch"); + + // PC should have been signed with the sp, so we verify that + // roundtripping does not fail. The `ptrauth_auth_and_resign` is + // guaranteed to trap on authentication failure even without FPAC + // feature. + pint_t pc = (pint_t)co->getReg(UNW_REG_IP); + if (ptrauth_auth_and_resign((void *)pc, ptrauth_key_return_address, sp, + ptrauth_key_return_address, + sp) != (void *)pc) { + _LIBUNWIND_LOG( + "Bad unwind with PAuth-enabled ABI (0x%zX, 0x%zX)->0x%zX\n", pc, + sp, + (pint_t)ptrauth_auth_data((void *)pc, ptrauth_key_return_address, + sp)); + _LIBUNWIND_ABORT("Bad unwind with PAuth-enabled ABI"); + } + } +#endif + // If the original call expects stack adjustment, perform this now. // Normal frame unwinding would have included the offset already in the // CFA computation. @@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, // this should actually be - info.gp. LLVM doesn't currently support // any such platforms and Clang doesn't export a macro for them. if (info.gp) - co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp, 0); + co->setReg(UNW_REG_SP, sp + info.gp); + co->setReg(UNW_REG_IP, value); + co->setInfoBasedOnIPRegister(false); + } else { + co->setReg(regNum, (pint_t)value); } return UNW_ESUCCESS; } @@ -175,21 +220,6 @@ _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, } _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg) -/// Get location of specified register at cursor position in stack frame. -_LIBUNWIND_HIDDEN int __unw_get_save_loc(unw_cursor_t *cursor, int regNum, - unw_save_loc_t* location) -{ - AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; - if (co->validReg(regNum)) { - // We only support memory locations, not register locations - location->u.addr = co->getRegLocation(regNum); - location->type = (location->u.addr == 0) ? UNW_SLT_NONE : UNW_SLT_MEMORY; - return UNW_ESUCCESS; - } - return UNW_EBADREG; -} -_LIBUNWIND_WEAK_ALIAS(__unw_get_save_loc, unw_get_save_loc) - /// Move cursor to next frame. _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast(cursor)); @@ -220,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, } _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) -/// Resume execution at cursor position (aka longjump). +/// Rebalance the execution flow by injecting the right amount of `ret` +/// instruction relatively to the amount of `walkedFrames` then resume execution +/// at cursor position (aka longjump). +_LIBUNWIND_HIDDEN int __unw_resume_with_frames_walked(unw_cursor_t *cursor, + unsigned walkedFrames) { + _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p, walkedFrames=%u)", + static_cast(cursor), walkedFrames); +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + // Inform the ASan runtime that now might be a good time to clean stuff up. + __asan_handle_no_return(); +#endif +#ifdef _LIBUNWIND_TRACE_RET_INJECT + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + co->setWalkedFrames(walkedFrames); +#endif + return __unw_resume(cursor); +} +_LIBUNWIND_WEAK_ALIAS(__unw_resume_with_frames_walked, + unw_resume_with_frames_walked) + +/// Legacy function. Resume execution at cursor position (aka longjump). _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast(cursor)); #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) @@ -362,6 +412,41 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +/// Maps the UNW_* error code to a textual representation +_LIBUNWIND_HIDDEN const char *__unw_strerror(int error_code) { + switch (error_code) { + case UNW_ESUCCESS: + return "no error"; + case UNW_EUNSPEC: + return "unspecified (general) error"; + case UNW_ENOMEM: + return "out of memory"; + case UNW_EBADREG: + return "bad register number"; + case UNW_EREADONLYREG: + return "attempt to write read-only register"; + case UNW_ESTOPUNWIND: + return "stop unwinding"; + case UNW_EINVALIDIP: + return "invalid IP"; + case UNW_EBADFRAME: + return "bad frame"; + case UNW_EINVAL: + return "unsupported operation or bad value"; + case UNW_EBADVERSION: + return "unwind info has unsupported version"; + case UNW_ENOINFO: + return "no unwind info found"; +#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY) + case UNW_ECROSSRASIGNING: + return "cross unwind with return address signing"; +#endif + } + return "invalid error code"; +} +_LIBUNWIND_WEAK_ALIAS(__unw_strerror, unw_strerror) + #endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) #ifdef __APPLE__ diff --git a/src/native/external/llvm-libunwind/src/libunwind_ext.h b/src/native/external/llvm-libunwind/src/libunwind_ext.h index db55939971264e..b3762c24d7da47 100644 --- a/src/native/external/llvm-libunwind/src/libunwind_ext.h +++ b/src/native/external/llvm-libunwind/src/libunwind_ext.h @@ -26,11 +26,16 @@ extern "C" { extern int __unw_getcontext(unw_context_t *); extern int __unw_init_local(unw_cursor_t *, unw_context_t *); extern int __unw_step(unw_cursor_t *); +extern int __unw_step_stage2(unw_cursor_t *); extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); -extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *); +extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t); extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t); -extern int __unw_resume(unw_cursor_t *); +_LIBUNWIND_TRACE_NO_INLINE + extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned); +// `__unw_resume` is a legacy function. Use `__unw_resume_with_frames_walked` instead. +_LIBUNWIND_TRACE_NO_INLINE + extern int __unw_resume(unw_cursor_t *); #ifdef __arm__ /* Save VFP registers in FSTMX format (instead of FSTMD). */ @@ -42,7 +47,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *); extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t); extern int __unw_is_signal_frame(unw_cursor_t *); extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); -extern int __unw_get_save_loc(unw_cursor_t *, int, unw_save_loc_t *); +extern const char *__unw_strerror(int); #if defined(_AIX) extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *); diff --git a/src/native/external/llvm-libunwind/src/cet_unwind.h b/src/native/external/llvm-libunwind/src/shadow_stack_unwind.h similarity index 83% rename from src/native/external/llvm-libunwind/src/cet_unwind.h rename to src/native/external/llvm-libunwind/src/shadow_stack_unwind.h index 47d7616a7322c3..b00ca2c9327c74 100644 --- a/src/native/external/llvm-libunwind/src/cet_unwind.h +++ b/src/native/external/llvm-libunwind/src/shadow_stack_unwind.h @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LIBUNWIND_CET_UNWIND_H -#define LIBUNWIND_CET_UNWIND_H +#ifndef LIBUNWIND_SHADOW_STACK_UNWIND_H +#define LIBUNWIND_SHADOW_STACK_UNWIND_H #include "libunwind.h" -// Currently, CET is implemented on Linux x86 platforms. -#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) +// Currently, CET is implemented on some ELF x86 platforms. +#if defined(__CET__) && defined(__SHSTK__) #define _LIBUNWIND_USE_CET 1 #endif @@ -21,7 +21,7 @@ #include #include -#define _LIBUNWIND_POP_CET_SSP(x) \ +#define _LIBUNWIND_POP_SHSTK_SSP(x) \ do { \ unsigned long ssp = _get_ssp(); \ if (ssp != 0) { \ @@ -46,7 +46,7 @@ #define _LIBUNWIND_USE_GCS 1 #endif -#define _LIBUNWIND_POP_CET_SSP(x) \ +#define _LIBUNWIND_POP_SHSTK_SSP(x) \ do { \ if (__chkfeat(_CHKFEAT_GCS)) { \ unsigned tmp = (x); \ @@ -57,7 +57,7 @@ #endif -extern void *__libunwind_cet_get_registers(unw_cursor_t *); -extern void *__libunwind_cet_get_jump_target(void); +extern void *__libunwind_shstk_get_registers(unw_cursor_t *); +extern void *__libunwind_shstk_get_jump_target(void); #endif diff --git a/src/native/external/llvm-libunwind/test/CMakeLists.txt b/src/native/external/llvm-libunwind/test/CMakeLists.txt index c222c0bdbf5af1..2559ab34f9d5b7 100644 --- a/src/native/external/llvm-libunwind/test/CMakeLists.txt +++ b/src/native/external/llvm-libunwind/test/CMakeLists.txt @@ -8,19 +8,22 @@ macro(pythonize_bool var) endif() endmacro() +# Install targets required to run libunwind tests into a temporary location. +# +# This ensures that we run the tests against the final installed products, which +# is closer to what we actually ship than the contents of the build tree. set(LIBUNWIND_TESTING_INSTALL_PREFIX "${LIBUNWIND_BINARY_DIR}/test-suite-install") -add_custom_target(libunwind-install-unwind-for-testing - DEPENDS unwind-headers - unwind - COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBUNWIND_TESTING_INSTALL_PREFIX}" - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=unwind-headers - -DCMAKE_INSTALL_PREFIX="${LIBUNWIND_TESTING_INSTALL_PREFIX}" - -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" - COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=unwind - -DCMAKE_INSTALL_PREFIX="${LIBUNWIND_TESTING_INSTALL_PREFIX}" - -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") +set(libunwind_test_suite_install_targets unwind-headers unwind) +if ("libcxx" IN_LIST LLVM_ENABLE_RUNTIMES) + list(APPEND libunwind_test_suite_install_targets cxx-headers cxx cxx-modules cxxabi-headers cxxabi) +endif() +foreach(target IN LISTS libunwind_test_suite_install_targets) + add_custom_target(libunwind-test-suite-install-${target} DEPENDS "${target}" + COMMAND "${CMAKE_COMMAND}" --install "${CMAKE_BINARY_DIR}" + --prefix "${LIBUNWIND_TESTING_INSTALL_PREFIX}" + --component "${target}") + add_dependencies(unwind-test-depends libunwind-test-suite-install-${target}) +endforeach() pythonize_bool(LIBUNWIND_ENABLE_CET) pythonize_bool(LIBUNWIND_ENABLE_GCS) @@ -62,4 +65,4 @@ configure_lit_site_cfg( add_lit_testsuite(check-unwind "Running libunwind tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS libunwind-install-unwind-for-testing) + DEPENDS unwind-test-depends) diff --git a/src/native/external/llvm-libunwind/test/aarch64_vg_unwind.pass.cpp b/src/native/external/llvm-libunwind/test/aarch64_vg_unwind.pass.cpp new file mode 100644 index 00000000000000..d0c623b155092d --- /dev/null +++ b/src/native/external/llvm-libunwind/test/aarch64_vg_unwind.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: target={{aarch64-.+}} +// UNSUPPORTED: target={{.*-windows.*}} + +#include +#include +#include + +// Basic test of VG (Vector Granule) unwinding. This is meant to mimic SVE/SME +// unwind info without requiring those features for this test. + +#define VG_REGNUM 46 + +__attribute__((noinline)) void baz() { + // The previous value of VG is 2 + asm(".cfi_escape 0x16, 0x2e, 0x01, 0x32"); + + unw_context_t context; + unw_cursor_t cursor; + unw_getcontext(&context); + unw_init_local(&cursor, &context); + + // Note: At this point VG is not defined (until we unw_step). + + uint16_t expected_vgs[]{/*qux*/ 2, /*bar*/ 2, /*foo*/ 8, /*main*/ 2}; + for (uint16_t expected_vg : expected_vgs) { + unw_step(&cursor); + unw_word_t vg; + unw_get_reg(&cursor, VG_REGNUM, &vg); + if (vg != expected_vg) + exit(1); + } + exit(0); +} + +__attribute__((noinline)) void qux() { baz(); } + +__attribute__((noinline)) void bar() { + // The previous value of VG is 8 + asm(".cfi_escape 0x16, 0x2e, 0x01, 0x38"); + // The previous value of W21 is VG (used to force an evaluation of VG). + asm(".cfi_escape 0x16, 0x15, 0x03, 0x92, 0x2e, 0x00"); + + // smstop sm + qux(); + // smstart sm +} +__attribute__((noinline)) void foo() { + // The previous value of VG is 2 + asm(".cfi_escape 0x16, 0x2e, 0x01, 0x32"); + // The previous value of W21 is VG (used to force an evaluation of VG). + asm(".cfi_escape 0x16, 0x15, 0x03, 0x92, 0x2e, 0x00"); + + // smstart sm + bar(); + // smstop sm +} + +int main(int, char **) { + foo(); + return 0; +} diff --git a/src/native/external/llvm-libunwind/test/aarch64_za_unwind.pass.cpp b/src/native/external/llvm-libunwind/test/aarch64_za_unwind.pass.cpp new file mode 100644 index 00000000000000..9f6b106a21fecb --- /dev/null +++ b/src/native/external/llvm-libunwind/test/aarch64_za_unwind.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: target={{aarch64-.+}} +// UNSUPPORTED: target={{.*-windows.*}} + +#include +#include +#include +#include +#include +#include + +// Basic test of unwinding with SME lazy saves. This tests libunwind disables ZA +// (and commits a lazy save of ZA) before resuming from unwinding. + +// Note: This test requires SME (and is setup to pass on targets without SME). + +static bool checkHasSME() { + constexpr int hwcap2_sme = (1 << 23); + unsigned long hwcap2 = getauxval(AT_HWCAP2); + return (hwcap2 & hwcap2_sme) != 0; +} + +struct TPIDR2Block { + void *za_save_buffer; + uint64_t num_save_slices; +}; + +__attribute__((noinline)) void private_za() { + // Note: Lazy save active on entry to function. + unw_context_t context; + unw_cursor_t cursor; + + unw_getcontext(&context); + unw_init_local(&cursor, &context); + unw_step(&cursor); + unw_resume(&cursor); +} + +bool isZAOn() { + register uint64_t svcr asm("x20"); + asm(".inst 0xd53b4254" : "=r"(svcr)); + return (svcr & 0b10) != 0; +} + +__attribute__((noinline)) void za_function_with_lazy_save() { + register uint64_t tmp asm("x8"); + + // SMSTART ZA (should zero ZA) + asm(".inst 0xd503457f"); + + // RDSVL x8, #1 (read streaming vector length) + asm(".inst 0x04bf5828" : "=r"(tmp)); + + // Allocate and fill ZA save buffer with 0xAA. + size_t buffer_size = tmp * tmp; + uint8_t *za_save_buffer = (uint8_t *)alloca(buffer_size); + memset(za_save_buffer, 0xAA, buffer_size); + + TPIDR2Block block = {za_save_buffer, tmp}; + tmp = reinterpret_cast(&block); + + // MRS TPIDR2_EL0, x8 (setup lazy save of ZA) + asm(".inst 0xd51bd0a8" ::"r"(tmp)); + + // ZA should be on before unwinding. + if (!isZAOn()) { + fprintf(stderr, __FILE__ ": fail (ZA not on before call)\n"); + abort(); + } else { + fprintf(stderr, __FILE__ ": pass (ZA on before call)\n"); + } + + private_za(); + + // ZA should be off after unwinding. + if (isZAOn()) { + fprintf(stderr, __FILE__ ": fail (ZA on after unwinding)\n"); + abort(); + } else { + fprintf(stderr, __FILE__ ": pass (ZA off after unwinding)\n"); + } + + // MRS x8, TPIDR2_EL0 (read TPIDR2_EL0) + asm(".inst 0xd53bd0a8" : "=r"(tmp)); + // ZA should have been saved (TPIDR2_EL0 zero). + if (tmp != 0) { + fprintf(stderr, __FILE__ ": fail (TPIDR2_EL0 non-null after unwinding)\n"); + abort(); + } else { + fprintf(stderr, __FILE__ ": pass (TPIDR2_EL0 null after unwinding)\n"); + } + + // ZA (all zero) should have been saved to the buffer. + for (unsigned i = 0; i < buffer_size; ++i) { + if (za_save_buffer[i] != 0) { + fprintf(stderr, + __FILE__ ": fail (za_save_buffer non-zero after unwinding)\n"); + abort(); + } + } + fprintf(stderr, __FILE__ ": pass (za_save_buffer zero'd after unwinding)\n"); +} + +int main(int, char **) { + if (!checkHasSME()) { + fprintf(stderr, __FILE__ ": pass (no SME support)\n"); + return 0; // Pass (SME is required for this test to run). + } + za_function_with_lazy_save(); + return 0; +} diff --git a/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S index 2c0cf140fe2672..056575745ea187 100644 --- a/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S +++ b/src/native/external/llvm-libunwind/test/aix_signal_unwind.pass.sh.S @@ -126,10 +126,11 @@ extern "C" __attribute__((noinline)) void foo() { bar(); } -int main() { +int main(int, char**) { // Set signal handler for SIGSEGV. signal(SIGSEGV, handler); foo(); + return 0; } #else // Assembly code for abc(). @@ -168,7 +169,7 @@ L..abc0: .vbyte 4, 0x00000000 # Traceback table begin .byte 0x00 # Version = 0 .byte 0x09 # Language = CPlusPlus - .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue + .byte 0x20 # -IsGlobalLinkage, -IsOutOfLineEpilogOrPrologue # +HasTraceBackTableOffset, -IsInternalProcedure # -HasControlledStorage, -IsTOCless # -IsFloatingPointPresent @@ -218,7 +219,7 @@ L..abc0: .vbyte 4, 0x00000000 # Traceback table begin .byte 0x00 # Version = 0 .byte 0x09 # Language = CPlusPlus - .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue + .byte 0x20 # -IsGlobalLinkage, -IsOutOfLineEpilogOrPrologue # +HasTraceBackTableOffset, -IsInternalProcedure # -HasControlledStorage, -IsTOCless # -IsFloatingPointPresent diff --git a/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp b/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp index b3284e8daed71f..332b661d2e98f1 100644 --- a/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp +++ b/src/native/external/llvm-libunwind/test/bad_unwind_info.pass.cpp @@ -10,7 +10,9 @@ // Ensure that libunwind doesn't crash on invalid info; the Linux aarch64 // sigreturn frame check would previously attempt to access invalid memory in // this scenario. -// REQUIRES: target={{(aarch64|s390x|x86_64)-.+linux.*}} +// REQUIRES: target={{(aarch64|s390x|x86_64)-.+}} +// UNSUPPORTED: target={{.*-windows.*}} +// UNSUPPORTED: target={{.*-apple.*}} // GCC doesn't support __attribute__((naked)) on AArch64. // UNSUPPORTED: gcc @@ -77,4 +79,7 @@ extern "C" void stepper() { assert(unw_step(&cursor) <= 0); } -int main() { bad_unwind_info(); } +int main(int, char **) { + bad_unwind_info(); + return 0; +} diff --git a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in index e5a7c983562a60..252448a756be9c 100644 --- a/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/apple-libunwind-system.cfg.in @@ -19,7 +19,7 @@ config.substitutions.append(('%{link_flags}', '-nostdlib++ -L %{lib} -lc++ -lunwind' )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T -- ' + '%{executor} --execdir %{temp} -- ' )) config.stdlib = 'apple-libc++' diff --git a/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in b/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in index e8f68a51fc53f8..6ffdd70c6177e7 100644 --- a/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in @@ -8,7 +8,7 @@ config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{include}' )) config.substitutions.append(('%{link_flags}', - '-nostdlib -nostdlib++ -L %{lib} -lunwind' + '-fuse-ld=lld -nostdlib -nostdlib++ -L %{lib} -lunwind' ' -lc -lm -lclang_rt.builtins -lsemihost -lcrt0-semihost' + ' -T {}'.format(libc_linker_script) + ' -Wl,--defsym=__flash=0x0' @@ -25,7 +25,7 @@ config.executor = ( ' --cpu cortex-m3') config.substitutions.append(('%{exec}', '%{executor}' - ' --execdir %T' + ' --execdir %{temp}' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in index b804c210f0bbc0..e40497bfa99766 100644 --- a/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/cmake-bridge.cfg.in @@ -14,6 +14,7 @@ import os, site site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils')) import libcxx.test.format +from lit.util import which # Basic configuration of the test suite config.name = os.path.basename('@LIBUNWIND_TEST_CONFIG@') @@ -33,3 +34,13 @@ config.substitutions.append(('%{install-prefix}', '@LIBUNWIND_TESTING_INSTALL_PR config.substitutions.append(('%{include}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/include')) config.substitutions.append(('%{lib}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/@LIBUNWIND_INSTALL_LIBRARY_DIR@')) config.substitutions.append(('%{benchmark_flags}', '')) + +# Check for objcopy tools +objcopy_path = which('llvm-objcopy', '@LLVM_BUILD_BINARY_DIR@/bin') +if not objcopy_path: + objcopy_path = which('llvm-objcopy') +if not objcopy_path: + objcopy_path = which('objcopy') +if objcopy_path: + config.substitutions.append(('%{objcopy}', objcopy_path)) + config.available_features.add('objcopy-available') diff --git a/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in b/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in index 2221e0cf499ff2..99f4a9061d19a7 100644 --- a/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/ibm-libunwind-shared.cfg.in @@ -17,7 +17,7 @@ config.substitutions.append(('%{link_flags}', '-nostdlib++ -L %{lib} -lunwind -ldl -Wl,-bbigtoc' )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T --env LIBPATH=%{lib} -- ' + '%{executor} --execdir %{temp} --env LIBPATH=%{lib} -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in index fafe12962b428f..34950f6ea29360 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-merged.cfg.in @@ -35,7 +35,7 @@ config.substitutions.append(('%{link_flags}', '-L %{{lib}} -Wl,-rpath,%{{lib}} -lc++ {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T -- ' + '%{executor} --execdir %{temp} -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in index b29d83fbab3053..1e77638b8cee3f 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in @@ -11,7 +11,7 @@ config.substitutions.append(('%{link_flags}', '-L %{lib} -lunwind' )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T --prepend_env PATH=%{install-prefix}/bin -- ' + '%{executor} --execdir %{temp} --prepend_env PATH=%{install-prefix}/bin -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in index f3e40928b525da..61d6b61cbae297 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-shared.cfg.in @@ -34,7 +34,7 @@ config.substitutions.append(('%{link_flags}', '-L %{{lib}} -Wl,-rpath,%{{lib}} -lunwind {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T -- ' + '%{executor} --execdir %{temp} -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in index 437c53bea2f06b..37d20a7c9a4494 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in @@ -11,7 +11,7 @@ config.substitutions.append(('%{link_flags}', '-L %{lib} -lunwind' )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T --prepend_env PATH=%{lib} -- ' + '%{executor} --execdir %{temp} --prepend_env PATH=%{lib} -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in index a3a65ae82591b1..194fa4f18f0e57 100644 --- a/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in +++ b/src/native/external/llvm-libunwind/test/configs/llvm-libunwind-static.cfg.in @@ -37,7 +37,7 @@ config.substitutions.append(('%{link_flags}', '%{{lib}}/libunwind.a {}'.format(' '.join(link_flags)) )) config.substitutions.append(('%{exec}', - '%{executor} --execdir %T -- ' + '%{executor} --execdir %{temp} -- ' )) import os, site diff --git a/src/native/external/llvm-libunwind/test/eh_frame_fde_pc_range.pass.cpp b/src/native/external/llvm-libunwind/test/eh_frame_fde_pc_range.pass.cpp new file mode 100644 index 00000000000000..32ddb769e6dcea --- /dev/null +++ b/src/native/external/llvm-libunwind/test/eh_frame_fde_pc_range.pass.cpp @@ -0,0 +1,61 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Manually marking the .eh_frame_hdr as DW_EH_PE_omit to make libunwind to do +// the linear search. +// Assuming the begining of the function is at the start of the FDE range. + +// clang-format off + +// REQUIRES: target={{x86_64-.+}} +// REQUIRES: objcopy-available +// UNSUPPORTED: target={{.*-windows.*}} +// UNSUPPORTED: target={{.*-apple.*}} + +// TODO: Figure out why this fails with Memory Sanitizer. +// XFAIL: msan + +// RUN: %{build} +// RUN: %{objcopy} --dump-section .eh_frame_hdr=%t_ehf_hdr.bin %t.exe +// RUN: printf '\377' | dd of=%t_ehf_hdr.bin bs=1 seek=2 count=2 conv=notrunc status=none +// RUN: %{objcopy} --update-section .eh_frame_hdr=%t_ehf_hdr.bin %t.exe +// RUN: %{exec} %t.exe + +// clang-format on + +#include +#include +#include +#include +#include + +void f() { + printf("123\n"); + void *pc = __builtin_return_address(0); + void *fpc = (void *)&f; + void *fpc1 = (void *)((uintptr_t)fpc + 1); + + struct dwarf_eh_bases bases; + const void *fde_pc = _Unwind_Find_FDE(pc, &bases); + const void *fde_fpc = _Unwind_Find_FDE(fpc, &bases); + const void *fde_fpc1 = _Unwind_Find_FDE(fpc1, &bases); + printf("fde_pc = %p\n", fde_pc); + printf("fde_fpc = %p\n", fde_fpc); + printf("fde_fpc1 = %p\n", fde_fpc1); + fflush(stdout); + assert(fde_pc != NULL); + assert(fde_fpc != NULL); + assert(fde_fpc1 != NULL); + assert(fde_fpc == fde_fpc1); +} + +int main(int, char **) { + f(); + return 0; +} diff --git a/src/native/external/llvm-libunwind/test/floatregister.pass.cpp b/src/native/external/llvm-libunwind/test/floatregister.pass.cpp index ce4481bdf8287e..6be3e1f3f7385f 100644 --- a/src/native/external/llvm-libunwind/test/floatregister.pass.cpp +++ b/src/native/external/llvm-libunwind/test/floatregister.pass.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -// REQUIRES: linux && target={{aarch64-.+}} +// REQUIRES: target={{aarch64-.+}} +// UNSUPPORTED: target={{.*-windows.*}} // Basic test for float registers number are accepted. @@ -52,7 +53,7 @@ __attribute__((noinline)) void foo() { _Unwind_Backtrace(frame_handler, NULL); } -__attribute__((section("main_func"))) int main() { +__attribute__((section("main_func"))) int main(int, char **) { foo(); return -2; } diff --git a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp index 344034e1ea5f5e..e5437c31a0f656 100644 --- a/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/forceunwind.pass.cpp @@ -7,7 +7,9 @@ // //===----------------------------------------------------------------------===// -// REQUIRES: linux +// UNSUPPORTED: target={{.*-apple.*}} +// UNSUPPORTED: target={{.*-aix.*}} +// UNSUPPORTED: target={{.*-windows.*}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan @@ -72,7 +74,7 @@ __attribute__((noinline)) void foo() { _Unwind_ForcedUnwind(e, stop, (void *)&foo); } -__attribute__((section("main_func"))) int main() { +__attribute__((section("main_func"))) int main(int, char **) { foo(); return -2; } diff --git a/src/native/external/llvm-libunwind/test/remember_state_leak.pass.sh.s b/src/native/external/llvm-libunwind/test/remember_state_leak.pass.sh.s index 63beb7e4701ec0..69be3f95955153 100644 --- a/src/native/external/llvm-libunwind/test/remember_state_leak.pass.sh.s +++ b/src/native/external/llvm-libunwind/test/remember_state_leak.pass.sh.s @@ -6,7 +6,9 @@ # #===------------------------------------------------------------------------===# -# REQUIRES: target={{x86_64-.+-linux-gnu}} +# REQUIRES: target={{x86_64-.+}} +# UNSUPPORTED: target={{.*-windows.*}} +# UNSUPPORTED: target={{.*-apple.*}} # Inline assembly isn't supported by Memory Sanitizer # UNSUPPORTED: msan @@ -38,6 +40,7 @@ SIZEOF_UNWIND_EXCEPTION = 32 + .att_syntax .text callback: xorl %eax, %eax diff --git a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp index 1c1566415a4d4b..ca50f83964c118 100644 --- a/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp +++ b/src/native/external/llvm-libunwind/test/signal_unwind.pass.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// // Ensure that the unwinder can cope with the signal handler. -// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}} +// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+}} +// UNSUPPORTED: target={{.*-windows.*}} +// UNSUPPORTED: target={{.*-apple.*}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan diff --git a/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp b/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp index 2b7470b5cad0eb..e1f40b4a42e947 100644 --- a/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unw_resume.pass.cpp @@ -25,7 +25,7 @@ __attribute__((noinline)) void test_unw_resume() { unw_resume(&cursor); } -int main() { +int main(int, char **) { test_unw_resume(); return 0; } diff --git a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp index 98de7dc43260c2..af791a6b2ed313 100644 --- a/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unwind_leaffunction.pass.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// // Ensure that leaf function can be unwund. -// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}} +// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+}} +// UNSUPPORTED: target={{.*-windows.*}} +// UNSUPPORTED: target={{.*-apple.*}} // TODO: Figure out why this fails with Memory Sanitizer. // XFAIL: msan diff --git a/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp b/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp index a5c5947c870fd1..38d8bd5e002d14 100644 --- a/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp +++ b/src/native/external/llvm-libunwind/test/unwind_scalable_vectors.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// REQUIRES: linux && target={{riscv64-.+}} +// REQUIRES: target={{riscv64-.+}} #undef NDEBUG #include @@ -34,7 +34,10 @@ __attribute__((noinline)) static void foo() { asm volatile("" ::"vr"(v)); // Dummy inline asm to use v. } -int main() { foo(); } +int main(int, char **) { + foo(); + return 0; +} #else -int main() { return 0; } +int main(int, char **) { return 0; } #endif From 35b7d59fa1075ab0fefb921393409806a821d8ed Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 14 Mar 2025 04:21:43 +0200 Subject: [PATCH 2/3] Apply patches --- .../nativeaot/Runtime/unix/UnwindHelpers.cpp | 2 + .../include/__libunwind_config.h | 29 +- .../llvm-libunwind/include/libunwind.h | 24 +- .../llvm-libunwind/include/unwind_arm_ehabi.h | 8 +- .../llvm-libunwind/include/unwind_itanium.h | 2 +- .../llvm-libunwind/src/AddressSpace.hpp | 35 +- .../llvm-libunwind/src/CompactUnwinder.hpp | 234 ++++++----- .../llvm-libunwind/src/DwarfInstructions.hpp | 58 ++- .../llvm-libunwind/src/DwarfParser.hpp | 10 +- .../external/llvm-libunwind/src/Registers.hpp | 374 +++++++++++++++--- .../llvm-libunwind/src/Unwind-EHABI.cpp | 32 +- .../llvm-libunwind/src/UnwindCursor.hpp | 56 ++- .../external/llvm-libunwind/src/config.h | 6 + .../external/llvm-libunwind/src/libunwind.cpp | 24 +- .../llvm-libunwind/src/libunwind_ext.h | 3 +- 15 files changed, 640 insertions(+), 257 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp index 8ead6c24ba94df..b1e51f8cad6782 100644 --- a/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/UnwindHelpers.cpp @@ -536,6 +536,8 @@ void Registers_REGDISPLAY::setFloatRegister(int num, unw_fpreg_t value) // Shim that implements methods required by libunwind over REGDISPLAY struct Registers_REGDISPLAY : REGDISPLAY { + typedef uint64_t reg_t; + inline static int getArch() { return libunwind::REGISTERS_ARM64; } static constexpr int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } diff --git a/src/native/external/llvm-libunwind/include/__libunwind_config.h b/src/native/external/llvm-libunwind/include/__libunwind_config.h index 980d11ef5d4f23..1210771f4182ab 100644 --- a/src/native/external/llvm-libunwind/include/__libunwind_config.h +++ b/src/native/external/llvm-libunwind/include/__libunwind_config.h @@ -41,8 +41,8 @@ # endif # if defined(__i386__) # define _LIBUNWIND_TARGET_I386 -# define _LIBUNWIND_CONTEXT_SIZE 8 -# define _LIBUNWIND_CURSOR_SIZE 15 +# define _LIBUNWIND_CONTEXT_SIZE 13 +# define _LIBUNWIND_CURSOR_SIZE 19 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 # elif defined(__x86_64__) # define _LIBUNWIND_TARGET_X86_64 1 @@ -57,8 +57,8 @@ # define _LIBUNWIND_CONTEXT_SIZE 21 # define _LIBUNWIND_CURSOR_SIZE 28 # else -# define _LIBUNWIND_CONTEXT_SIZE 21 -# define _LIBUNWIND_CURSOR_SIZE 33 +# define _LIBUNWIND_CONTEXT_SIZE 38 +# define _LIBUNWIND_CURSOR_SIZE 50 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 # elif defined(__powerpc64__) @@ -73,11 +73,11 @@ # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC # elif defined(__aarch64__) # define _LIBUNWIND_TARGET_AARCH64 1 -#define _LIBUNWIND_CONTEXT_SIZE 67 +# define _LIBUNWIND_CONTEXT_SIZE 100 # if defined(__SEH__) -# define _LIBUNWIND_CURSOR_SIZE 164 +# define _LIBUNWIND_CURSOR_SIZE 198 # else -#define _LIBUNWIND_CURSOR_SIZE 79 +# define _LIBUNWIND_CURSOR_SIZE 112 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 # elif defined(__arm__) @@ -89,8 +89,8 @@ # define _LIBUNWIND_CONTEXT_SIZE 61 # define _LIBUNWIND_CURSOR_SIZE 68 # else -# define _LIBUNWIND_CONTEXT_SIZE 42 -# define _LIBUNWIND_CURSOR_SIZE 49 +# define _LIBUNWIND_CONTEXT_SIZE 50 +# define _LIBUNWIND_CURSOR_SIZE 57 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM # elif defined(__or1k__) @@ -154,7 +154,7 @@ # else # define RISCV_FLEN 0 # endif -# define _LIBUNWIND_CONTEXT_SIZE (32 * (__riscv_xlen + RISCV_FLEN) / 64) +# define _LIBUNWIND_CONTEXT_SIZE (32 * (__riscv_xlen + RISCV_FLEN) / 64) + 32 # if __riscv_xlen == 32 # define _LIBUNWIND_CURSOR_SIZE (_LIBUNWIND_CONTEXT_SIZE + 7) # elif __riscv_xlen == 64 @@ -176,8 +176,13 @@ #elif defined(__loongarch__) #define _LIBUNWIND_TARGET_LOONGARCH 1 #if __loongarch_grlen == 64 -#define _LIBUNWIND_CONTEXT_SIZE 65 -#define _LIBUNWIND_CURSOR_SIZE 77 +#define _LIBUNWIND_CONTEXT_SIZE 98 +#define _LIBUNWIND_CURSOR_SIZE 110 +#elif defined(HOST_WASM) +#define _LIBUNWIND_TARGET_WASM 1 +// TODO: Determine the right values +#define _LIBUNWIND_CONTEXT_SIZE 0xbadf00d +#define _LIBUNWIND_CURSOR_SIZE 0xbadf00d #else #error "Unsupported LoongArch ABI" #endif diff --git a/src/native/external/llvm-libunwind/include/libunwind.h b/src/native/external/llvm-libunwind/include/libunwind.h index 56ca7110274a30..6084196e04bea0 100644 --- a/src/native/external/llvm-libunwind/include/libunwind.h +++ b/src/native/external/llvm-libunwind/include/libunwind.h @@ -206,6 +206,26 @@ struct unw_proc_info_t { }; typedef struct unw_proc_info_t unw_proc_info_t; +enum unw_save_loc_type_t +{ + UNW_SLT_NONE, /* register is not saved ("not an l-value") */ + UNW_SLT_MEMORY, /* register has been saved in memory */ + UNW_SLT_REG /* register has been saved in (another) register */ +}; +typedef enum unw_save_loc_type_t unw_save_loc_type_t; + +struct unw_save_loc_t +{ + unw_save_loc_type_t type; + union + { + unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ + unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ + } + u; +}; +typedef struct unw_save_loc_t unw_save_loc_t; + #ifdef __cplusplus extern "C" { #endif @@ -215,7 +235,7 @@ extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; -extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; +extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; @@ -233,7 +253,7 @@ extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; -//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); +extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*) LIBUNWIND_AVAIL; extern const char *unw_strerror(int) LIBUNWIND_AVAIL; extern unw_addr_space_t unw_local_addr_space; diff --git a/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h b/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h index 68e02e47602d60..fa38def6ade841 100644 --- a/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h +++ b/src/native/external/llvm-libunwind/include/unwind_arm_ehabi.h @@ -118,7 +118,7 @@ _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, extern _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); + void *valuep, uintptr_t *pos); extern _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, @@ -150,8 +150,8 @@ uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); + uintptr_t value, uintptr_t *pos) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value, pos); } _LIBUNWIND_EXPORT_UNWIND_LEVEL1 @@ -163,7 +163,7 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, value | thumb_bit); + _Unwind_SetGR(context, 15, value | thumb_bit, NULL); } #ifdef __cplusplus diff --git a/src/native/external/llvm-libunwind/include/unwind_itanium.h b/src/native/external/llvm-libunwind/include/unwind_itanium.h index d94a6183be2901..7e813c7c2b07a0 100644 --- a/src/native/external/llvm-libunwind/include/unwind_itanium.h +++ b/src/native/external/llvm-libunwind/include/unwind_itanium.h @@ -65,7 +65,7 @@ extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value); + uintptr_t new_value, uintptr_t *pos); extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); diff --git a/src/native/external/llvm-libunwind/src/AddressSpace.hpp b/src/native/external/llvm-libunwind/src/AddressSpace.hpp index 52477b16b355aa..435232dff8f423 100644 --- a/src/native/external/llvm-libunwind/src/AddressSpace.hpp +++ b/src/native/external/llvm-libunwind/src/AddressSpace.hpp @@ -22,6 +22,7 @@ #include "dwarf2.h" #include "EHHeaderParser.hpp" #include "Registers.hpp" +#include "libunwind_ext.h" #ifndef _LIBUNWIND_USE_DLADDR #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX)) @@ -47,11 +48,20 @@ struct EHABIIndexEntry { #if defined(_AIX) namespace libunwind { + char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, unw_word_t *offset); } #endif +namespace libunwind { + +struct LocalAddressSpaceDefaultArgType { + typedef uintptr_t link_hardened_reg_arg_t; +}; + +} + #ifdef __APPLE__ struct dyld_unwind_sections @@ -202,6 +212,10 @@ class _LIBUNWIND_HIDDEN LocalAddressSpace { pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase = 0, pint_t *resultAddr = nullptr); + bool findFunctionName(pint_t addr, char *buf, size_t bufLen, + unw_word_t *offset); + bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); + bool findOtherFDE(pint_t targetAddr, pint_t &fde); template bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf, size_t bufLen, unw_word_t *offset); @@ -619,11 +633,7 @@ inline bool LocalAddressSpace::findUnwindSections( // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind // support for _dl_find_object on other unwind formats is not implemented, // yet. -#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. -#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME -#error _dl_find_object retrieves an unexpected section type -#endif +#if defined(DLFO_STRUCT_HAS_EH_DBASE) && defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) && DLFO_EH_SEGMENT_TYPE == PT_GNU_EH_FRAME // We look-up `dl_find_object` dynamically at runtime to ensure backwards // compatibility with earlier version of glibc not yet providing it. On older // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer @@ -674,6 +684,21 @@ inline bool LocalAddressSpace::findUnwindSections( return false; } +inline bool LocalAddressSpace::findUnwindSections( + pint_t targetAddr, UnwindInfoSections &info) { + return findUnwindSections(targetAddr, info); +} + +inline bool LocalAddressSpace::findFunctionName( + pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { + return findFunctionName(addr, buf, bufLen, + offset); +} + +inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { + return findOtherFDE(targetAddr, fde); +} + template inline bool LocalAddressSpace::findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, diff --git a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp index cd2e0e3431314a..389bd37dcafc21 100644 --- a/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp +++ b/src/native/external/llvm-libunwind/src/CompactUnwinder.hpp @@ -29,34 +29,34 @@ 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 +template class CompactUnwinder_x86 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); + R ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, Registers_x86 ®isters); + static void frameUnwind(A &addressSpace, R ®isters); static void framelessUnwind(A &addressSpace, typename A::pint_t returnAddressLocation, - Registers_x86 ®isters); + R ®isters); static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, - Registers_x86 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); + A &addressSpace, R ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86::stepWithCompactEncoding( +template +int CompactUnwinder_x86::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_X86_MODE_MASK) { case UNWIND_X86_MODE_EBP_FRAME: return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, @@ -71,10 +71,10 @@ int CompactUnwinder_x86::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( +template +int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters) { + A &addressSpace, R ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -87,19 +87,19 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( // no register saved in this slot break; case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); + registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); + registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); + registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); + registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); + registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); break; default: (void)functionStart; @@ -115,10 +115,10 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint32_t functionStart, - A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { + A &addressSpace, R ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -204,22 +204,22 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); + registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); + registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); + registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); + registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); + registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EBP: - registers.setEBP(addressSpace.get32(savedRegisters)); + registers.setEBP(addressSpace.get32(savedRegisters), savedRegisters); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -234,26 +234,26 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86::frameUnwind(A &addressSpace, - Registers_x86 ®isters) { +template +void CompactUnwinder_x86::frameUnwind(A &addressSpace, + R ®isters) { typename A::pint_t bp = registers.getEBP(); // ebp points to old ebp - registers.setEBP(addressSpace.get32(bp)); + registers.setEBP(addressSpace.get32(bp), bp); // old esp is ebp less saved ebp and return address - registers.setSP((uint32_t)bp + 8); + registers.setSP((uint32_t)bp + 8, 0); // pop return address into eip - registers.setIP(addressSpace.get32(bp + 4)); + registers.setIP(addressSpace.get32(bp + 4), bp + 4); } -template -void CompactUnwinder_x86::framelessUnwind( +template +void CompactUnwinder_x86::framelessUnwind( A &addressSpace, typename A::pint_t returnAddressLocation, - Registers_x86 ®isters) { + R ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get32(returnAddressLocation)); + registers.setIP(addressSpace.get32(returnAddressLocation), returnAddressLocation); // old esp is before return address - registers.setSP((uint32_t)returnAddressLocation + 4); + registers.setSP((uint32_t)returnAddressLocation + 4, 0); } #endif // _LIBUNWIND_TARGET_I386 @@ -261,33 +261,33 @@ void CompactUnwinder_x86::framelessUnwind( #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 +template class CompactUnwinder_x86_64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); + R ®isters); private: typename A::pint_t pint_t; - static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); + static void frameUnwind(A &addressSpace, R ®isters); static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, - Registers_x86_64 ®isters); + R ®isters); static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); + A &addressSpace, R ®isters, bool indirectStackSize); }; -template -int CompactUnwinder_x86_64::stepWithCompactEncoding( +template +int CompactUnwinder_x86_64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { case UNWIND_X86_64_MODE_RBP_FRAME: return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, @@ -302,10 +302,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_x86_64 ®isters) { + A &addressSpace, R ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); uint32_t savedRegistersLocations = @@ -318,19 +318,19 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( // no register saved in this slot break; case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); + registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); + registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); + registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); + registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); + registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); break; default: (void)functionStart; @@ -346,10 +346,10 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, - Registers_x86_64 ®isters, bool indirectStackSize) { + R ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = @@ -435,22 +435,22 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); + registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); + registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); + registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); + registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); + registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_RBP: - registers.setRBP(addressSpace.get64(savedRegisters)); + registers.setRBP(addressSpace.get64(savedRegisters), savedRegisters); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -465,26 +465,26 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( } -template -void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, - Registers_x86_64 ®isters) { +template +void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, + R ®isters) { uint64_t rbp = registers.getRBP(); // ebp points to old ebp - registers.setRBP(addressSpace.get64(rbp)); + registers.setRBP(addressSpace.get64(rbp), rbp); // old esp is ebp less saved ebp and return address - registers.setSP(rbp + 16); + registers.setSP(rbp + 16, 0); // pop return address into eip - registers.setIP(addressSpace.get64(rbp + 8)); + registers.setIP(addressSpace.get64(rbp + 8), rbp + 8); } -template -void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, - uint64_t returnAddressLocation, - Registers_x86_64 ®isters) { +template +void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, + uint64_t returnAddressLocation, + R ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get64(returnAddressLocation)); + registers.setIP(addressSpace.get64(returnAddressLocation), returnAddressLocation); // old esp is before return address - registers.setSP(returnAddressLocation + 8); + registers.setSP(returnAddressLocation + 8, 0); } #endif // _LIBUNWIND_TARGET_X86_64 @@ -493,13 +493,13 @@ void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, #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 +template class CompactUnwinder_arm64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); + R ®isters); private: typename A::pint_t pint_t; @@ -507,16 +507,16 @@ class CompactUnwinder_arm64 { static int stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, - Registers_arm64 ®isters); + R ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters); + A &addressSpace, R ®isters); }; -template -int CompactUnwinder_arm64::stepWithCompactEncoding( +template +int CompactUnwinder_arm64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, - A &addressSpace, Registers_arm64 ®isters) { + A &addressSpace, R ®isters) { switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: return stepWithCompactEncodingFrame(compactEncoding, functionStart, @@ -528,43 +528,43 @@ int CompactUnwinder_arm64::stepWithCompactEncoding( _LIBUNWIND_ABORT("invalid compact unwind encoding"); } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { + R ®isters) { uint32_t stackSize = 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); uint64_t savedRegisterLoc = registers.getSP() + stackSize; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } @@ -606,50 +606,50 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( Registers_arm64::reg_t linkRegister = registers.getRegister(UNW_AARCH64_LR); // subtract stack size off of sp - registers.setSP(savedRegisterLoc); + registers.setSP(savedRegisterLoc, 0); // Set pc to be value in lr. This needs to be performed after the new SP has // been set, as the PC authentication schema entangles the SP of the new // frame. - registers.setIP(linkRegister); + registers.setIP(linkRegister, 0); return UNW_STEP_SUCCESS; } -template -int CompactUnwinder_arm64::stepWithCompactEncodingFrame( +template +int CompactUnwinder_arm64::stepWithCompactEncodingFrame( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, - Registers_arm64 ®isters) { - Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8; + R ®isters) { + typename R::reg_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } @@ -689,15 +689,11 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrame( Registers_arm64::reg_t fp = registers.getFP(); // fp points to old fp - registers.setFP(addressSpace.get64(fp)); - - // Old sp is fp less saved fp and lr. We need to set this prior to setting - // the lr as the pointer authentication schema for the lr incorporates the - // sp as part of the diversifier. - registers.setSP(fp + 16); - + registers.setFP(addressSpace.get64(fp), fp); + // old sp is fp less saved fp and lr + registers.setSP(fp + 16, 0); // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8)); + registers.setIP(addressSpace.get64(fp + 8), fp + 8); return UNW_STEP_SUCCESS; } diff --git a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp index 165c4a99e9a92f..1fc8baa8036b07 100644 --- a/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfInstructions.hpp @@ -34,7 +34,7 @@ class DwarfInstructions { typedef typename A::sint_t sint_t; static int stepWithDwarf(A &addressSpace, - typename R::link_hardened_reg_arg_t pc, + pint_t pc, pint_t fdeStart, R ®isters, bool &isSignalFrame, bool stage2); @@ -57,7 +57,8 @@ class DwarfInstructions { const R ®isters, pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); + pint_t cfa, const RegisterLocation &savedReg, + pint_t& location); static double getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, @@ -94,24 +95,28 @@ template uint64_t getSparcWCookie(const R &, long) { template typename A::pint_t DwarfInstructions::getSavedRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { + const RegisterLocation &savedReg, + typename A::pint_t& location) { switch (savedReg.location) { case CFI_Parser::kRegisterInCFA: - return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); + location = cfa + (pint_t)savedReg.value; + return (pint_t)addressSpace.getP(location); case CFI_Parser::kRegisterInCFADecrypt: // sparc64 specific return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^ getSparcWCookie(registers, 0)); case CFI_Parser::kRegisterAtExpression: - return (pint_t)addressSpace.getRegister(evaluateExpression( - (pint_t)savedReg.value, addressSpace, registers, cfa)); + location = evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa); + return (pint_t)addressSpace.getP(location); case CFI_Parser::kRegisterIsExpression: + location = 0; return evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa); - case CFI_Parser::kRegisterInRegister: + location = 0; return registers.getRegister((int)savedReg.value); case CFI_Parser::kRegisterUndefined: return 0; @@ -181,11 +186,12 @@ bool DwarfInstructions::isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, PrologInfo &prolog) { pint_t raSignState; + pint_t location; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; if (regloc.location == CFI_Parser::kRegisterUnused) raSignState = static_cast(regloc.value); else - raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc, location); // Only bit[0] is meaningful. return raSignState & 0x01; @@ -197,11 +203,12 @@ bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, pint_t cfa, PrologInfo &prolog) { pint_t raSignState; + pint_t location; auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; if (regloc.location == CFI_Parser::kRegisterUnused) raSignState = static_cast(regloc.value); else - raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); + raSignState = getSavedRegister(addressSpace, registers, cfa, regloc, location); // Only bit[1] is meaningful. return raSignState & 0x02; @@ -210,7 +217,7 @@ bool DwarfInstructions::isReturnAddressSignedWithPC(A &addressSpace, template int DwarfInstructions::stepWithDwarf( - A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart, + A &addressSpace, pint_t pc, pint_t fdeStart, R ®isters, bool &isSignalFrame, bool stage2) { FDE_Info fdeInfo; CIE_Info cieInfo; @@ -226,7 +233,7 @@ int DwarfInstructions::stepWithDwarf( // __unw_step_stage2 is not used for cross unwinding, so we use // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are // building for AArch64 natively. -#if defined(__aarch64__) +#if 0 // defined(__aarch64__) if (stage2 && cieInfo.mteTaggedFrame) { pint_t sp = registers.getSP(); pint_t p = sp; @@ -264,9 +271,10 @@ int DwarfInstructions::stepWithDwarf( // // We set the SP here to the CFA, allowing for it to be overridden // by a CFI directive later on. - newRegisters.setSP(cfa); + newRegisters.setSP(cfa, 0); - typename R::reg_t returnAddress = 0; + pint_t returnAddress = 0; + pint_t returnAddressLocation = 0; constexpr int lastReg = R::lastDwarfRegNum(); static_assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg, @@ -284,13 +292,23 @@ int DwarfInstructions::stepWithDwarf( newRegisters.setVectorRegister( i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else if (i == (int)cieInfo.returnAddressRegister) + else if (i == (int)cieInfo.returnAddressRegister) { returnAddress = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i]); - else if (registers.validRegister(i)) - newRegisters.setRegister( - i, getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); + prolog.savedRegisters[i], + returnAddressLocation); + if (registers.validRegister(i)) { + newRegisters.setRegister(i, returnAddress, returnAddressLocation); + } + } + else if (registers.validRegister(i)) { + pint_t value; + pint_t location; + value = getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i], + location); + + newRegisters.setRegister(i, value, location); + } else return UNW_EBADREG; } else if (i == (int)cieInfo.returnAddressRegister) { @@ -411,7 +429,7 @@ int DwarfInstructions::stepWithDwarf( // Return address is address after call site instruction, so setting IP to // that does simulates a return. - newRegisters.setIP(returnAddress); + newRegisters.setIP(returnAddress, returnAddressLocation); // Simulate the step by replacing the register set with the new ones. registers = newRegisters; diff --git a/src/native/external/llvm-libunwind/src/DwarfParser.hpp b/src/native/external/llvm-libunwind/src/DwarfParser.hpp index 22de49023cb452..55c29f7103ef6e 100644 --- a/src/native/external/llvm-libunwind/src/DwarfParser.hpp +++ b/src/native/external/llvm-libunwind/src/DwarfParser.hpp @@ -161,7 +161,7 @@ class CFI_Parser { }; template - static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, + static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, @@ -170,7 +170,7 @@ class CFI_Parser { template static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, - typename R::link_hardened_reg_arg_t upToPC, + pint_t upToPC, int arch, PrologInfo *results); static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); @@ -244,7 +244,7 @@ const char *CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, template template bool CFI_Parser::findFDE(A &addressSpace, - typename R::link_hardened_reg_arg_t pc, + pint_t pc, pint_t ehSectionStart, size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo) { @@ -460,7 +460,7 @@ template template bool CFI_Parser::parseFDEInstructions( A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, - typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) { + pint_t upToPC, int arch, PrologInfo *results) { // Alloca is used for the allocation of the rememberStack entries. It removes // the dependency on new/malloc but the below for loop can not be refactored // into functions. Entry could be saved during the processing of a CIE and @@ -494,7 +494,7 @@ bool CFI_Parser::parseFDEInstructions( static_cast(instructionsEnd)); // see DWARF Spec, section 6.4.2 for details on unwind opcodes - while ((p < instructionsEnd) && (codeOffset < pcoffset)) { + while ((p < instructionsEnd) && (codeOffset <= pcoffset)) { uint64_t reg; uint64_t reg2; int64_t offset; diff --git a/src/native/external/llvm-libunwind/src/Registers.hpp b/src/native/external/llvm-libunwind/src/Registers.hpp index 474b17461bf77e..7d7afca8e9e1d2 100644 --- a/src/native/external/llvm-libunwind/src/Registers.hpp +++ b/src/native/external/llvm-libunwind/src/Registers.hpp @@ -72,7 +72,8 @@ class _LIBUNWIND_HIDDEN Registers_x86 { bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); + void setRegister(int num, uint32_t value, uint32_t location); + uint32_t getRegisterLocation(int num) const; bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -87,21 +88,21 @@ class _LIBUNWIND_HIDDEN Registers_x86 { static int getArch() { return REGISTERS_X86; } uint32_t getSP() const { return _registers.__esp; } - void setSP(uint32_t value) { _registers.__esp = value; } + void setSP(uint32_t value, uint32_t location) { _registers.__esp = value; _registerLocations.__esp = location; } uint32_t getIP() const { return _registers.__eip; } - void setIP(uint32_t value) { _registers.__eip = value; } + void setIP(uint32_t value, uint32_t location) { _registers.__eip = value; _registerLocations.__eip = location; } uint32_t getEBP() const { return _registers.__ebp; } - void setEBP(uint32_t value) { _registers.__ebp = value; } + void setEBP(uint32_t value, uint32_t location) { _registers.__ebp = value; _registerLocations.__ebp = location; } uint32_t getEBX() const { return _registers.__ebx; } - void setEBX(uint32_t value) { _registers.__ebx = value; } + void setEBX(uint32_t value, uint32_t location) { _registers.__ebx = value; _registerLocations.__ebx = location; } uint32_t getECX() const { return _registers.__ecx; } - void setECX(uint32_t value) { _registers.__ecx = value; } + void setECX(uint32_t value, uint32_t location) { _registers.__ecx = value; _registerLocations.__ecx = location; } uint32_t getEDX() const { return _registers.__edx; } - void setEDX(uint32_t value) { _registers.__edx = value; } + void setEDX(uint32_t value, uint32_t location) { _registers.__edx = value; _registerLocations.__edx = location; } uint32_t getESI() const { return _registers.__esi; } - void setESI(uint32_t value) { _registers.__esi = value; } + void setESI(uint32_t value, uint32_t location) { _registers.__esi = value; _registerLocations.__esi = location; } uint32_t getEDI() const { return _registers.__edi; } - void setEDI(uint32_t value) { _registers.__edi = value; } + void setEDI(uint32_t value, uint32_t location) { _registers.__edi = value; _registerLocations.__edi = location; } private: struct GPRs { @@ -122,18 +123,32 @@ class _LIBUNWIND_HIDDEN Registers_x86 { unsigned int __fs; unsigned int __gs; }; + struct GPRLocations { + unsigned int __eax; + unsigned int __ebx; + unsigned int __ecx; + unsigned int __edx; + unsigned int __edi; + unsigned int __esi; + unsigned int __ebp; + unsigned int __esp; + unsigned int __eip; + }; GPRs _registers; + GPRLocations _registerLocations; }; inline Registers_x86::Registers_x86(const void *registers) { static_assert((check_fit::does_fit), "x86 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86::Registers_x86() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86::validRegister(int regNum) const { @@ -182,25 +197,31 @@ inline uint32_t Registers_x86::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86 register"); } -inline void Registers_x86::setRegister(int regNum, uint32_t value) { +inline void Registers_x86::setRegister(int regNum, uint32_t value, uint32_t location) { switch (regNum) { case UNW_REG_IP: _registers.__eip = value; + _registerLocations.__eip = location; return; case UNW_REG_SP: _registers.__esp = value; + _registerLocations.__esp = location; return; case UNW_X86_EAX: _registers.__eax = value; + _registerLocations.__eax = location; return; case UNW_X86_ECX: _registers.__ecx = value; + _registerLocations.__ecx = location; return; case UNW_X86_EDX: _registers.__edx = value; + _registerLocations.__edx = location; return; case UNW_X86_EBX: _registers.__ebx = value; + _registerLocations.__ebx = location; return; #if !defined(__APPLE__) case UNW_X86_ESP: @@ -208,6 +229,7 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) { case UNW_X86_EBP: #endif _registers.__ebp = value; + _registerLocations.__ebp = location; return; #if !defined(__APPLE__) case UNW_X86_EBP: @@ -215,17 +237,46 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) { case UNW_X86_ESP: #endif _registers.__esp = value; + _registerLocations.__esp = location; return; case UNW_X86_ESI: _registers.__esi = value; + _registerLocations.__esi = location; return; case UNW_X86_EDI: _registers.__edi = value; + _registerLocations.__edi = location; return; } _LIBUNWIND_ABORT("unsupported x86 register"); } +inline uint32_t Registers_x86::getRegisterLocation(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registerLocations.__eip; + case UNW_REG_SP: + return _registerLocations.__esp; + case UNW_X86_EAX: + return _registerLocations.__eax; + case UNW_X86_ECX: + return _registerLocations.__ecx; + case UNW_X86_EDX: + return _registerLocations.__edx; + case UNW_X86_EBX: + return _registerLocations.__ebx; + case UNW_X86_EBP: + return _registerLocations.__ebp; + case UNW_X86_ESP: + return _registerLocations.__esp; + case UNW_X86_ESI: + return _registerLocations.__esi; + case UNW_X86_EDI: + return _registerLocations.__edi; + } + _LIBUNWIND_ABORT("unsupported x86 register"); +} + inline const char *Registers_x86::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -294,7 +345,8 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); + uint64_t getRegisterLocation(int num) const; bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -309,21 +361,21 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { static int getArch() { return REGISTERS_X86_64; } uint64_t getSP() const { return _registers.__rsp; } - void setSP(uint64_t value) { _registers.__rsp = value; } + void setSP(uint64_t value, uint64_t location) { _registers.__rsp = value; _registerLocations.__rsp = location;} uint64_t getIP() const { return _registers.__rip; } - void setIP(uint64_t value) { _registers.__rip = value; } + void setIP(uint64_t value, uint64_t location) { _registers.__rip = value; _registerLocations.__rip = location; } uint64_t getRBP() const { return _registers.__rbp; } - void setRBP(uint64_t value) { _registers.__rbp = value; } + void setRBP(uint64_t value, uint64_t location) { _registers.__rbp = value; _registerLocations.__rbp = location; } uint64_t getRBX() const { return _registers.__rbx; } - void setRBX(uint64_t value) { _registers.__rbx = value; } + void setRBX(uint64_t value, uint64_t location) { _registers.__rbx = value; _registerLocations.__rbx = location; } uint64_t getR12() const { return _registers.__r12; } - void setR12(uint64_t value) { _registers.__r12 = value; } + void setR12(uint64_t value, uint64_t location) { _registers.__r12 = value; _registerLocations.__r12 = location; } uint64_t getR13() const { return _registers.__r13; } - void setR13(uint64_t value) { _registers.__r13 = value; } + void setR13(uint64_t value, uint64_t location) { _registers.__r13 = value; _registerLocations.__r13 = location; } uint64_t getR14() const { return _registers.__r14; } - void setR14(uint64_t value) { _registers.__r14 = value; } + void setR14(uint64_t value, uint64_t location) { _registers.__r14 = value; _registerLocations.__r14 = location; } uint64_t getR15() const { return _registers.__r15; } - void setR15(uint64_t value) { _registers.__r15 = value; } + void setR15(uint64_t value, uint64_t location) { _registers.__r15 = value; _registerLocations.__r15 = location; } private: struct GPRs { @@ -352,7 +404,27 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { uint64_t __padding; // 16-byte align #endif }; + struct GPRLocations { + uint64_t __rax; + uint64_t __rbx; + uint64_t __rcx; + uint64_t __rdx; + uint64_t __rdi; + uint64_t __rsi; + uint64_t __rbp; + uint64_t __rsp; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __rip; + }; GPRs _registers; + GPRLocations _registerLocations; #if defined(_WIN64) v128 _xmm[16]; #endif @@ -362,10 +434,12 @@ inline Registers_x86_64::Registers_x86_64(const void *registers) { static_assert((check_fit::does_fit), "x86_64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86_64::Registers_x86_64() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86_64::validRegister(int regNum) const { @@ -423,62 +497,122 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86_64 register"); } -inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { +inline uint64_t Registers_x86_64::getRegisterLocation(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registerLocations.__rip; + case UNW_REG_SP: + return _registerLocations.__rsp; + case UNW_X86_64_RAX: + return _registerLocations.__rax; + case UNW_X86_64_RDX: + return _registerLocations.__rdx; + case UNW_X86_64_RCX: + return _registerLocations.__rcx; + case UNW_X86_64_RBX: + return _registerLocations.__rbx; + case UNW_X86_64_RSI: + return _registerLocations.__rsi; + case UNW_X86_64_RDI: + return _registerLocations.__rdi; + case UNW_X86_64_RBP: + return _registerLocations.__rbp; + case UNW_X86_64_RSP: + return _registerLocations.__rsp; + case UNW_X86_64_R8: + return _registerLocations.__r8; + case UNW_X86_64_R9: + return _registerLocations.__r9; + case UNW_X86_64_R10: + return _registerLocations.__r10; + case UNW_X86_64_R11: + return _registerLocations.__r11; + case UNW_X86_64_R12: + return _registerLocations.__r12; + case UNW_X86_64_R13: + return _registerLocations.__r13; + case UNW_X86_64_R14: + return _registerLocations.__r14; + case UNW_X86_64_R15: + return _registerLocations.__r15; + } + _LIBUNWIND_ABORT("unsupported x86_64 register"); +} + +inline void Registers_x86_64::setRegister(int regNum, uint64_t value, uint64_t location) { switch (regNum) { case UNW_REG_IP: case UNW_X86_64_RIP: _registers.__rip = value; + _registerLocations.__rip = location; return; case UNW_REG_SP: _registers.__rsp = value; + _registerLocations.__rsp = location; return; case UNW_X86_64_RAX: _registers.__rax = value; + _registerLocations.__rax = location; return; case UNW_X86_64_RDX: _registers.__rdx = value; + _registerLocations.__rdx = location; return; case UNW_X86_64_RCX: _registers.__rcx = value; + _registerLocations.__rcx = location; return; case UNW_X86_64_RBX: _registers.__rbx = value; + _registerLocations.__rbx = location; return; case UNW_X86_64_RSI: _registers.__rsi = value; + _registerLocations.__rsi = location; return; case UNW_X86_64_RDI: _registers.__rdi = value; + _registerLocations.__rdi = location; return; case UNW_X86_64_RBP: _registers.__rbp = value; + _registerLocations.__rbp = location; return; case UNW_X86_64_RSP: _registers.__rsp = value; + _registerLocations.__rsp = location; return; case UNW_X86_64_R8: _registers.__r8 = value; + _registerLocations.__r8 = location; return; case UNW_X86_64_R9: _registers.__r9 = value; + _registerLocations.__r9 = location; return; case UNW_X86_64_R10: _registers.__r10 = value; + _registerLocations.__r10 = location; return; case UNW_X86_64_R11: _registers.__r11 = value; + _registerLocations.__r11 = location; return; case UNW_X86_64_R12: _registers.__r12 = value; + _registerLocations.__r12 = location; return; case UNW_X86_64_R13: _registers.__r13 = value; + _registerLocations.__r13 = location; return; case UNW_X86_64_R14: _registers.__r14 = value; + _registerLocations.__r14 = location; return; case UNW_X86_64_R15: _registers.__r15 = value; + _registerLocations.__r15 = location; return; } _LIBUNWIND_ABORT("unsupported x86_64 register"); @@ -1193,7 +1327,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); + uint64_t getRegisterLocation(int num) const; bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -1866,13 +2001,14 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); 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); + uint64_t getRegisterLocation(int regNum) const; static const char *getRegisterName(int num); void jumpto(unsigned walkedFrames = 0) { zaDisable(); @@ -1888,7 +2024,10 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { static int getArch() { return REGISTERS_ARM64; } uint64_t getSP() const { return _registers.__sp; } - void setSP(uint64_t value) { _registers.__sp = value; } + void setSP(uint64_t value, uint64_t location) { + _registers.__sp = value; + _registerLocations.__sp = location; + } uint64_t getIP() const { uint64_t value = _registers.__pc; #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) @@ -1902,7 +2041,7 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { #endif return value; } - void setIP(uint64_t value) { + void setIP(uint64_t value, uint64_t location) { #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) // Note the value which was set should have been signed with the SP. // We then resign with the slot we are being stored in to so that both SP @@ -1914,9 +2053,13 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { &_registers.__pc); #endif _registers.__pc = value; + _registerLocations.__pc = location; } uint64_t getFP() const { return _registers.__fp; } - void setFP(uint64_t value) { _registers.__fp = value; } + void setFP(uint64_t value, uint64_t location) { + _registers.__fp = value; + _registerLocations.__fp = location; + } #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) void @@ -1960,12 +2103,21 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { uint64_t __ra_sign_state = 0; // RA sign state register }; + struct GPRLocations { + uint64_t __x[29] = {}; // x0-x28 + uint64_t __fp = 0; // Frame pointer x29 + uint64_t __lr = 0; // Link register x30 + uint64_t __sp = 0; // Stack pointer x31 + uint64_t __pc = 0; // Program counter + }; + struct Misc { mutable uint32_t __vg = 0; // Vector Granule bool __has_sme = checkHasSME(); }; GPRs _registers = {}; + GPRLocations _registerLocations = {}; // Currently only the lower double in 128-bit vectore registers // is perserved during unwinding. We could define new register // numbers (> 96) which mean whole vector registers, then this @@ -1983,7 +2135,9 @@ inline Registers_arm64::Registers_arm64(const void *registers) { static_assert((check_fit::does_fit), "arm64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - static_assert(sizeof(GPRs) == 0x110, + memset(&_registerLocations, 0, sizeof(_registerLocations)); + static_assert( + sizeof(GPRs) == 0x110, "expected VFP registers to be at offset 272"); memcpy(_vectorHalfRegisters, static_cast(registers) + sizeof(GPRs), @@ -1998,7 +2152,7 @@ inline Registers_arm64::Registers_arm64(const void *registers) { uint64_t pcRegister = 0; memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc), sizeof(pcRegister)); - setIP(pcRegister); + setIP(pcRegister, 0); #endif } @@ -2011,7 +2165,7 @@ Registers_arm64::operator=(const Registers_arm64 &other) { memmove(static_cast(this), &other, sizeof(*this)); // We perform this step to ensure that we correctly authenticate and re-sign // the pc after the bitwise copy. - setIP(other.getIP()); + setIP(other.getIP(), other.getRegisterLocation(UNW_REG_IP)); return *this; } @@ -2065,25 +2219,53 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported arm64 register"); } -inline void Registers_arm64::setRegister(int regNum, uint64_t value) { +inline void Registers_arm64::setRegister(int regNum, uint64_t value, uint64_t location) { if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) - setIP(value); - else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) + setIP(value, location); + else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) { _registers.__sp = value; + _registerLocations.__sp = location; + } else if (regNum == UNW_AARCH64_RA_SIGN_STATE) _registers.__ra_sign_state = value; - else if (regNum == UNW_AARCH64_FP) - setFP(value); - else if (regNum == UNW_AARCH64_LR) + else if (regNum == UNW_AARCH64_FP) { + _registers.__fp = value; + _registerLocations.__fp = location; + } + else if (regNum == UNW_AARCH64_LR) { _registers.__lr = value; + _registerLocations.__lr = location; + } + else if ((regNum >= 0) && (regNum < 29)) { + _registers.__x[regNum] = value; + _registerLocations.__x[regNum] = location; + } else if (regNum == UNW_AARCH64_VG) _misc_registers.__vg = value; - else if ((regNum >= 0) && (regNum < 29)) - _registers.__x[regNum] = value; else _LIBUNWIND_ABORT("unsupported arm64 register"); } +inline uint64_t Registers_arm64::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_IP) + return _registerLocations.__pc; + if (regNum == UNW_AARCH64_PC) + return _registerLocations.__pc; + if (regNum == UNW_REG_SP) + return _registerLocations.__sp; + if (regNum == UNW_AARCH64_SP) + return _registerLocations.__sp; + if (regNum == UNW_AARCH64_FP) + return _registerLocations.__fp; + if (regNum == UNW_AARCH64_LR) + return _registerLocations.__lr; + if ((regNum >= 0) && (regNum < 29)) + return _registerLocations.__x[regNum]; + if (regNum == UNW_AARCH64_RA_SIGN_STATE || regNum == UNW_AARCH64_VG) + return 0; + _LIBUNWIND_ABORT("unsupported arm64 register"); +} + inline const char *Registers_arm64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -2273,7 +2455,8 @@ class _LIBUNWIND_HIDDEN Registers_arm { bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); + void setRegister(int num, uint32_t value, uint32_t location); + uint32_t getRegisterLocation(int num) const; bool validFloatRegister(int num) const; unw_fpreg_t getFloatRegister(int num); void setFloatRegister(int num, unw_fpreg_t value); @@ -2291,9 +2474,9 @@ class _LIBUNWIND_HIDDEN Registers_arm { static int getArch() { return REGISTERS_ARM; } uint32_t getSP() const { return _registers.__sp; } - void setSP(uint32_t value) { _registers.__sp = value; } + void setSP(uint32_t value, uint32_t location) { _registers.__sp = value; _registerLocations.__sp = location; } uint32_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value) { _registers.__pc = value; } + void setIP(uint32_t value, uint32_t location) { _registers.__pc = value; _registerLocations.__pc = location; } void saveVFPAsX() { assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); @@ -2330,6 +2513,14 @@ class _LIBUNWIND_HIDDEN Registers_arm { }; static void saveVFPWithFSTMD(void*); + + struct GPRLocations { + uint32_t __r[13]; // r0-r12 + uint32_t __sp; // Stack pointer r13 + uint32_t __lr; // Link register r14 + uint32_t __pc; // Program counter r15 + }; + static void saveVFPWithFSTMX(void*); static void saveVFPv3(void*); static void restoreVFPWithFLDMD(void*); @@ -2346,6 +2537,7 @@ class _LIBUNWIND_HIDDEN Registers_arm { // ARM registers GPRs _registers; PseudoRegisters _pseudo_registers; + GPRLocations _registerLocations; // We save floating point registers lazily because we can't know ahead of // time which ones are used. See EHABI #4.7. @@ -2384,6 +2576,7 @@ inline Registers_arm::Registers_arm(const void *registers) // See __unw_getcontext() note about data. memcpy(&_registers, registers, sizeof(_registers)); memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2400,6 +2593,7 @@ inline Registers_arm::Registers_arm() _saved_vfp_d16_d31(false) { memset(&_registers, 0, sizeof(_registers)); memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2466,24 +2660,28 @@ inline uint32_t Registers_arm::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported arm register"); } -inline void Registers_arm::setRegister(int regNum, uint32_t value) { +inline void Registers_arm::setRegister(int regNum, uint32_t value, uint32_t location) { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { _registers.__sp = value; + _registerLocations.__sp = location; return; } if (regNum == UNW_ARM_LR) { _registers.__lr = value; + _registerLocations.__lr = location; return; } if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { _registers.__pc = value; + _registerLocations.__pc = location; return; } if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { _registers.__r[regNum] = value; + _registerLocations.__r[regNum] = location; return; } @@ -2506,6 +2704,22 @@ inline void Registers_arm::setRegister(int regNum, uint32_t value) { _LIBUNWIND_ABORT("unsupported arm register"); } +inline uint32_t Registers_arm::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) + return _registerLocations.__sp; + + if (regNum == UNW_ARM_LR) + return _registerLocations.__lr; + + if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) + return _registerLocations.__pc; + + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) + return _registerLocations.__r[regNum]; + + _LIBUNWIND_ABORT("unsupported arm register"); +} + inline const char *Registers_arm::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -4229,13 +4443,14 @@ class _LIBUNWIND_HIDDEN Registers_riscv { bool validRegister(int num) const; reg_t getRegister(int num) const; - void setRegister(int num, reg_t value); + void setRegister(int num, reg_t value, uint64_t location); bool validFloatRegister(int num) const; fp_t getFloatRegister(int num) const; void setFloatRegister(int num, fp_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); + uint64_t getRegisterLocation(int num) const; static const char *getRegisterName(int num); void jumpto(); static constexpr int lastDwarfRegNum() { @@ -4244,13 +4459,14 @@ class _LIBUNWIND_HIDDEN Registers_riscv { static int getArch() { return REGISTERS_RISCV; } reg_t getSP() const { return _registers[2]; } - void setSP(reg_t value) { _registers[2] = value; } + void setSP(reg_t value, uint64_t location) { _registers[2] = value; } reg_t getIP() const { return _registers[0]; } - void setIP(reg_t value) { _registers[0] = value; } + void setIP(reg_t value, uint64_t location) { _registers[0] = value; } private: // _registers[0] holds the pc reg_t _registers[32]; + reg_t _registerLocations[32]; # if defined(__riscv_flen) fp_t _floats[32]; # endif @@ -4260,6 +4476,7 @@ inline Registers_riscv::Registers_riscv(const void *registers) { static_assert((check_fit::does_fit), "riscv registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); # if __riscv_xlen == 32 static_assert(sizeof(_registers) == 0x80, "expected float registers to be at offset 128"); @@ -4279,6 +4496,7 @@ inline Registers_riscv::Registers_riscv(const void *registers) { inline Registers_riscv::Registers_riscv() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); # if defined(__riscv_flen) memset(&_floats, 0, sizeof(_floats)); # endif @@ -4315,20 +4533,41 @@ inline reg_t Registers_riscv::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported riscv register"); } -inline void Registers_riscv::setRegister(int regNum, reg_t value) { - if (regNum == UNW_REG_IP) +inline void Registers_riscv::setRegister(int regNum, reg_t value, uint64_t location) { + if (regNum == UNW_REG_IP) { _registers[0] = value; + _registerLocations[0] = value; + } else if (regNum == UNW_REG_SP) _registers[2] = value; else if (regNum == UNW_RISCV_X0) /* x0 is hardwired to zero */ return; - else if ((regNum > 0) && (regNum < 32)) + else if ((regNum > 0) && (regNum < 32)) { _registers[regNum] = value; + _registerLocations[regNum - UNW_RISCV_X0] = location; + } else _LIBUNWIND_ABORT("unsupported riscv register"); } +inline uint64_t Registers_riscv::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_IP) + return _registerLocations[0]; + if (regNum == UNW_REG_SP) + return _registerLocations[2]; + if (regNum == UNW_RISCV_X0) + return 0; + if ((regNum > 0) && (regNum < 32)) + return _registerLocations[regNum]; + if (regNum == UNW_RISCV_VLENB) { + reg_t vlenb; + __asm__("csrr %0, 0xC22" : "=r"(vlenb)); + return vlenb; + } + _LIBUNWIND_ABORT("unsupported riscv register"); +} + inline const char *Registers_riscv::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -5269,13 +5508,14 @@ class _LIBUNWIND_HIDDEN Registers_loongarch { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); 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); + uint64_t getRegisterLocation(int num) const; static const char *getRegisterName(int num); void jumpto(); static constexpr int lastDwarfRegNum() { @@ -5284,17 +5524,23 @@ class _LIBUNWIND_HIDDEN Registers_loongarch { static int getArch() { return REGISTERS_LOONGARCH; } uint64_t getSP() const { return _registers.__r[3]; } - void setSP(uint64_t value) { _registers.__r[3] = value; } + void setSP(uint64_t value, uint64_t location) { _registers.__r[3] = value; } uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value) { _registers.__pc = value; } + void setIP(uint64_t value, uint64_t location) { _registers.__pc = value; } private: - struct loongarch_thread_state_t { + struct GPRs { uint64_t __r[32]; uint64_t __pc; }; - loongarch_thread_state_t _registers; + struct GPRLocations { + uint64_t __r[32]; + uint64_t __pc; + }; + + GPRs _registers; + GPRLocations _registerLocations; #if __loongarch_frlen == 64 double _floats[32]; #endif @@ -5304,6 +5550,7 @@ inline Registers_loongarch::Registers_loongarch(const void *registers) { static_assert((check_fit::does_fit), "loongarch registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); static_assert(sizeof(_registers) == 0x108, "expected float registers to be at offset 264"); #if __loongarch_frlen == 64 @@ -5314,6 +5561,7 @@ inline Registers_loongarch::Registers_loongarch(const void *registers) { inline Registers_loongarch::Registers_loongarch() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); #if __loongarch_frlen == 64 memset(&_floats, 0, sizeof(_floats)); #endif @@ -5338,17 +5586,33 @@ inline uint64_t Registers_loongarch::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported loongarch register"); } -inline void Registers_loongarch::setRegister(int regNum, uint64_t value) { - if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) +inline void Registers_loongarch::setRegister(int regNum, uint64_t value, uint64_t location) { + if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) { _registers.__r[regNum - UNW_LOONGARCH_R0] = value; - else if (regNum == UNW_REG_IP) + _registerLocations.__r[regNum - UNW_LOONGARCH_R0] = location; + } + else if (regNum == UNW_REG_IP) { _registers.__pc = value; - else if (regNum == UNW_REG_SP) + _registerLocations.__pc = location; + } + else if (regNum == UNW_REG_SP) { _registers.__r[3] = value; + _registerLocations.__r[3] = location; + } else _LIBUNWIND_ABORT("unsupported loongarch register"); } +inline uint64_t Registers_loongarch::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_IP) + return _registerLocations.__pc; + if (regNum == UNW_REG_SP) + return _registerLocations.__r[3]; + if ((regNum >= 0) && (regNum < 32)) + return _registerLocations.__r[regNum]; + _LIBUNWIND_ABORT("unsupported loongarch64 register"); +} + inline const char *Registers_loongarch::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: diff --git a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp index 05475c6ac1e2fe..338c853bca780e 100644 --- a/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp +++ b/src/native/external/llvm-libunwind/src/Unwind-EHABI.cpp @@ -228,7 +228,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { // only by the personality routine. Fortunately, all existing assembler // implementations, including GNU assembler, LLVM integrated assembler, // and ARM assembler, assume that the unwind opcodes come after the - // personality rountine address. + // personality routine address. *off = 1; // First byte is size data. *len = (((data[1] >> 24) & 0xff) + 1) * 4; data++; // Skip the first word, which is the prel31 offset. @@ -271,7 +271,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, sp -= (((uint32_t)byte & 0x3f) << 2) + 4; else sp += ((uint32_t)byte << 2) + 4; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); } else { switch (byte & 0xf0) { case 0x80: { @@ -295,7 +295,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, _UVRSD_UINT32, &sp); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xa0: { @@ -337,7 +337,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, &sp); sp += 0x204 + (addend << 2); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xb3: { @@ -438,7 +438,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, #else (void)hasReturnAddrAuthCode; #endif - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr, NULL); } return _URC_CONTINUE_UNWIND; } @@ -589,7 +589,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor // // See #7.4.6 for details. __unw_set_reg(cursor, UNW_REG_IP, - exception_object->unwinder_cache.reserved2); + exception_object->unwinder_cache.reserved2, NULL); resume = false; } @@ -909,7 +909,7 @@ ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, _LIBUNWIND_EXPORT _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep) { + void *valuep, unw_word_t *pos) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " "rep=%d, value=0x%llX)", static_cast(context), regclass, regno, @@ -921,7 +921,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - *(unw_word_t *)valuep) == UNW_ESUCCESS + *(unw_word_t *)valuep,(unw_word_t *)pos) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: @@ -965,7 +965,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno != 0) return _UVRSR_FAILED; return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), - *(unw_word_t *)valuep) == UNW_ESUCCESS + *(unw_word_t *)valuep, NULL) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; break; @@ -1071,6 +1071,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // computed new stack location. See EHABI #7.5.4 table 3. bool poppedSP = false; uint32_t* sp; + uint32_t* pos; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; @@ -1078,17 +1079,18 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, for (uint32_t i = 0; i < 16; ++i) { if (!(discriminator & static_cast(1 << i))) continue; + pos = sp; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) poppedSP = true; if (_Unwind_VRS_Set(context, regclass, i, - _UVRSD_UINT32, &value) != _UVRSR_OK) { + _UVRSD_UINT32, &value, pos) != _UVRSR_OK) { return _UVRSR_FAILED; } } if (!poppedSP) { return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp); + _UVRSD_UINT32, &sp, NULL); } return _UVRSR_OK; } @@ -1120,14 +1122,14 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, #else #error "Unable to determine endianess" #endif - if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != + if (_Unwind_VRS_Set(context, regclass, i, representation, &value, NULL) != _UVRSR_OK) return _UVRSR_FAILED; } if (representation == _UVRSD_VFPX) ++sp; return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); } case _UVRSC_PSEUDO: { if (representation != _UVRSD_UINT32 || discriminator != 0) @@ -1139,8 +1141,8 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, return _UVRSR_FAILED; } uint32_t pac = *sp++; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); - return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); + return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac, NULL); } } _LIBUNWIND_ABORT("unsupported register class"); diff --git a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp index 5838dbcaa9980a..144833d9d647ce 100644 --- a/src/native/external/llvm-libunwind/src/UnwindCursor.hpp +++ b/src/native/external/llvm-libunwind/src/UnwindCursor.hpp @@ -460,9 +460,12 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { virtual ~AbstractUnwindCursor() {} virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } - virtual void setReg(int, unw_word_t) { + virtual void setReg(int, unw_word_t, unw_word_t) { _LIBUNWIND_ABORT("setReg not implemented"); } + virtual unw_word_t getRegLocation(int) { + _LIBUNWIND_ABORT("getRegLocation not implemented"); + } virtual bool validFloatReg(int) { _LIBUNWIND_ABORT("validFloatReg not implemented"); } @@ -966,12 +969,14 @@ template class UnwindCursor : public AbstractUnwindCursor{ typedef typename A::pint_t pint_t; public: + UnwindCursor(A &as); UnwindCursor(unw_context_t *context, A &as); UnwindCursor(A &as, void *threadArg); virtual ~UnwindCursor() {} virtual bool validReg(int); virtual unw_word_t getReg(int); - virtual void setReg(int, unw_word_t); + virtual void setReg(int, unw_word_t, unw_word_t); + virtual unw_word_t getRegLocation(int); virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); @@ -1006,6 +1011,7 @@ class UnwindCursor : public AbstractUnwindCursor{ private: #if defined(_LIBUNWIND_ARM_EHABI) +public: bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); int stepWithEHABI() { @@ -1065,9 +1071,13 @@ class UnwindCursor : public AbstractUnwindCursor{ const typename CFI_Parser::CIE_Info &cieInfo, typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base); + +public: bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint = 0); + +private: int stepWithDwarfFDE(bool stage2) { #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) typename R::reg_t rawPC = this->getReg(UNW_REG_IP); @@ -1083,8 +1093,10 @@ class UnwindCursor : public AbstractUnwindCursor{ #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) +public: bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections §s); +private: int stepWithCompactEncoding(bool stage2 = false) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) if ( compactSaysUseDwarf() ) @@ -1379,6 +1391,13 @@ class UnwindCursor : public AbstractUnwindCursor{ #endif }; +template +UnwindCursor::UnwindCursor(A &as) + : _addressSpace(as) + , _unwindInfoMissing(false) + , _isSignalFrame(false) { + memset(&_info, 0, sizeof(_info)); +} template UnwindCursor::UnwindCursor(unw_context_t *context, A &as) @@ -1392,9 +1411,10 @@ UnwindCursor::UnwindCursor(unw_context_t *context, A &as) } template -UnwindCursor::UnwindCursor(A &as, void *) - : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { - memset(static_cast(&_info), 0, sizeof(_info)); +UnwindCursor::UnwindCursor(A &as, void *arg) + : _addressSpace(as),_registers(arg), _unwindInfoMissing(false), + _isSignalFrame(false) { + memset(&_info, 0, sizeof(_info)); // FIXME // fill in _registers from thread arg } @@ -1411,8 +1431,13 @@ unw_word_t UnwindCursor::getReg(int regNum) { } template -void UnwindCursor::setReg(int regNum, unw_word_t value) { - _registers.setRegister(regNum, (typename A::pint_t)value); +void UnwindCursor::setReg(int regNum, unw_word_t value, unw_word_t location) { + _registers.setRegister(regNum, (typename A::pint_t)value, (typename A::pint_t)location); +} + +template +unw_word_t UnwindCursor::getRegLocation(int regNum) { + return _registers.getRegisterLocation(regNum); } template @@ -1765,12 +1790,14 @@ bool UnwindCursor::getInfoFromDwarfSection( typename CFI_Parser::CIE_Info cieInfo; bool foundFDE = false; bool foundInCache = false; + // If compact encoding table gave offset into dwarf section, go directly there if (fdeSectionOffsetHint != 0) { foundFDE = CFI_Parser::template findFDE( _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); } + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (!foundFDE && (sects.dwarf_index_section != 0)) { foundFDE = EHHeaderParser::template findFDE( @@ -1778,6 +1805,7 @@ bool UnwindCursor::getInfoFromDwarfSection( (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); } #endif + if (!foundFDE) { // otherwise, search cache of previously found FDEs. pint_t cachedFDE = @@ -2942,10 +2970,10 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { for (int i = 0; i <= 30; ++i) { uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs + static_cast(i * 8)); - _registers.setRegister(UNW_AARCH64_X0 + i, value); + _registers.setRegister(UNW_AARCH64_X0 + i, value, 0); } - _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp)); - _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc)); + _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp), 0); + _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc), 0); _isSignalFrame = true; return UNW_STEP_SUCCESS; } @@ -2994,12 +3022,12 @@ int UnwindCursor::stepThroughSigReturn(Registers_loongarch &) { const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; - _registers.setIP(_addressSpace.get64(sigctx)); + _registers.setIP(_addressSpace.get64(sigctx), 0); for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) { // skip R0 uint64_t value = _addressSpace.get64(sigctx + static_cast((i + 1) * 8)); - _registers.setRegister(i, value); + _registers.setRegister(i, value, 0); } _isSignalFrame = true; return UNW_STEP_SUCCESS; @@ -3049,10 +3077,10 @@ int UnwindCursor::stepThroughSigReturn(Registers_riscv &) { const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; - _registers.setIP(_addressSpace.get64(sigctx)); + _registers.setIP(_addressSpace.get64(sigctx), 0); for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) { uint64_t value = _addressSpace.get64(sigctx + static_cast(i * 8)); - _registers.setRegister(i, value); + _registers.setRegister(i, value, 0); } _isSignalFrame = true; return UNW_STEP_SUCCESS; diff --git a/src/native/external/llvm-libunwind/src/config.h b/src/native/external/llvm-libunwind/src/config.h index f017403fa2234f..960e1ffe71abbd 100644 --- a/src/native/external/llvm-libunwind/src/config.h +++ b/src/native/external/llvm-libunwind/src/config.h @@ -99,9 +99,15 @@ __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname)) #elif defined(__ELF__) || defined(_AIX) || defined(__wasm__) +#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 9) +#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ + extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ + __attribute__((weak, alias(#name), copy(name))); +#else #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ __attribute__((weak, alias(#name))); +#endif #elif defined(_WIN32) #if defined(__MINGW32__) #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ diff --git a/src/native/external/llvm-libunwind/src/libunwind.cpp b/src/native/external/llvm-libunwind/src/libunwind.cpp index 7ffffc2a30c0ae..2f2032c6c28147 100644 --- a/src/native/external/llvm-libunwind/src/libunwind.cpp +++ b/src/native/external/llvm-libunwind/src/libunwind.cpp @@ -111,13 +111,14 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg) /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t value) { + unw_word_t value, unw_word_t *pos) { _LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", static_cast(cursor), regNum, value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { + co->setReg(regNum, (pint_t)value, (pint_t)pos); // special case altering IP to re-find info (being called by personality // function) if (regNum == UNW_REG_IP) { @@ -174,11 +175,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, // this should actually be - info.gp. LLVM doesn't currently support // any such platforms and Clang doesn't export a macro for them. if (info.gp) - co->setReg(UNW_REG_SP, sp + info.gp); - co->setReg(UNW_REG_IP, value); + co->setReg(UNW_REG_SP, sp + info.gp, 0); + co->setReg(UNW_REG_IP, value, (pint_t)pos); co->setInfoBasedOnIPRegister(false); } else { - co->setReg(regNum, (pint_t)value); + co->setReg(regNum, (pint_t)value, (pint_t)pos); } return UNW_ESUCCESS; } @@ -220,6 +221,21 @@ _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, } _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg) +/// Get location of specified register at cursor position in stack frame. +_LIBUNWIND_HIDDEN int __unw_get_save_loc(unw_cursor_t *cursor, int regNum, + unw_save_loc_t* location) +{ + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validReg(regNum)) { + // We only support memory locations, not register locations + location->u.addr = co->getRegLocation(regNum); + location->type = (location->u.addr == 0) ? UNW_SLT_NONE : UNW_SLT_MEMORY; + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} +_LIBUNWIND_WEAK_ALIAS(__unw_get_save_loc, unw_get_save_loc) + /// Move cursor to next frame. _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast(cursor)); diff --git a/src/native/external/llvm-libunwind/src/libunwind_ext.h b/src/native/external/llvm-libunwind/src/libunwind_ext.h index b3762c24d7da47..da77ea3c4dab75 100644 --- a/src/native/external/llvm-libunwind/src/libunwind_ext.h +++ b/src/native/external/llvm-libunwind/src/libunwind_ext.h @@ -29,7 +29,7 @@ extern int __unw_step(unw_cursor_t *); extern int __unw_step_stage2(unw_cursor_t *); extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); -extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t); +extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *); extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t); _LIBUNWIND_TRACE_NO_INLINE extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned); @@ -48,6 +48,7 @@ extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t); extern int __unw_is_signal_frame(unw_cursor_t *); extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); extern const char *__unw_strerror(int); +extern int __unw_get_save_loc(unw_cursor_t *, int, unw_save_loc_t *); #if defined(_AIX) extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *); From 5423b289beb80e9977dc58a4f6276a7622be7d29 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:10:58 +0200 Subject: [PATCH 3/3] Update version file --- src/native/external/llvm-libunwind-version.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/external/llvm-libunwind-version.txt b/src/native/external/llvm-libunwind-version.txt index 118dfa206d0323..fcbda3180e207a 100644 --- a/src/native/external/llvm-libunwind-version.txt +++ b/src/native/external/llvm-libunwind-version.txt @@ -1,4 +1,4 @@ -v20.1.0 -https://github.com/llvm/llvm-project/releases/tag/llvmorg-20.1.0 +v22.1.1 +https://github.com/llvm/llvm-project/releases/tag/llvmorg-22.1.1 -Apply https://github.com/dotnet/runtime/commit/d03d1ba7835fdf9e2a6bb537d49fb5ff6584697b +Apply https://github.com/dotnet/runtime/commit/35b7d59fa1075ab0fefb921393409806a821d8ed