Index: projects/clang1000-import/contrib/llvm-project/libunwind/include/__libunwind_config.h =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/include/__libunwind_config.h (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/include/__libunwind_config.h (revision 357209) @@ -1,158 +1,151 @@ //===------------------------- __libunwind_config.h -----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef ____LIBUNWIND_CONFIG_H__ #define ____LIBUNWIND_CONFIG_H__ #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ !defined(__ARM_DWARF_EH__) #define _LIBUNWIND_ARM_EHABI #endif #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 95 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__i386__) # define _LIBUNWIND_TARGET_I386 # 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 # if defined(_WIN64) # define _LIBUNWIND_CONTEXT_SIZE 54 # ifdef __SEH__ # define _LIBUNWIND_CURSOR_SIZE 204 # else # define _LIBUNWIND_CURSOR_SIZE 66 # endif # else # define _LIBUNWIND_CONTEXT_SIZE 21 # define _LIBUNWIND_CURSOR_SIZE 33 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 # elif defined(__powerpc64__) # define _LIBUNWIND_TARGET_PPC64 1 # define _LIBUNWIND_CONTEXT_SIZE 167 # define _LIBUNWIND_CURSOR_SIZE 179 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 # elif defined(__ppc__) # define _LIBUNWIND_TARGET_PPC 1 # define _LIBUNWIND_CONTEXT_SIZE 117 # define _LIBUNWIND_CURSOR_SIZE 124 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC # elif defined(__aarch64__) # define _LIBUNWIND_TARGET_AARCH64 1 # define _LIBUNWIND_CONTEXT_SIZE 66 # if defined(__SEH__) # define _LIBUNWIND_CURSOR_SIZE 164 # else # define _LIBUNWIND_CURSOR_SIZE 78 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 # elif defined(__arm__) # define _LIBUNWIND_TARGET_ARM 1 # if defined(__SEH__) # define _LIBUNWIND_CONTEXT_SIZE 42 # define _LIBUNWIND_CURSOR_SIZE 80 # elif defined(__ARM_WMMX) # define _LIBUNWIND_CONTEXT_SIZE 61 # define _LIBUNWIND_CURSOR_SIZE 68 # else # define _LIBUNWIND_CONTEXT_SIZE 42 # define _LIBUNWIND_CURSOR_SIZE 49 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM # elif defined(__or1k__) # define _LIBUNWIND_TARGET_OR1K 1 # define _LIBUNWIND_CONTEXT_SIZE 16 # define _LIBUNWIND_CURSOR_SIZE 24 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K -# elif defined(__riscv) -# define _LIBUNWIND_TARGET_RISCV 1 -# define _LIBUNWIND_CONTEXT_SIZE 64 -# define _LIBUNWIND_CURSOR_SIZE 76 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV -# define _LIBUNWIND_MAX_REGISTER 96 # elif defined(__mips__) # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define _LIBUNWIND_TARGET_MIPS_O32 1 # if defined(__mips_hard_float) # define _LIBUNWIND_CONTEXT_SIZE 50 # define _LIBUNWIND_CURSOR_SIZE 57 # else # define _LIBUNWIND_CONTEXT_SIZE 18 # define _LIBUNWIND_CURSOR_SIZE 24 # endif # elif defined(_ABIN32) && _MIPS_SIM == _ABIN32 # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 # if defined(__mips_hard_float) # define _LIBUNWIND_CONTEXT_SIZE 67 # define _LIBUNWIND_CURSOR_SIZE 74 # else # define _LIBUNWIND_CONTEXT_SIZE 35 # define _LIBUNWIND_CURSOR_SIZE 42 # endif # elif defined(_ABI64) && _MIPS_SIM == _ABI64 # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 # if defined(__mips_hard_float) # define _LIBUNWIND_CONTEXT_SIZE 67 # define _LIBUNWIND_CURSOR_SIZE 79 # else # define _LIBUNWIND_CONTEXT_SIZE 35 # define _LIBUNWIND_CURSOR_SIZE 47 # endif # else # error "Unsupported MIPS ABI and/or environment" # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS # elif defined(__sparc__) #define _LIBUNWIND_TARGET_SPARC 1 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC #define _LIBUNWIND_CONTEXT_SIZE 16 #define _LIBUNWIND_CURSOR_SIZE 23 # elif defined(__riscv) # if __riscv_xlen == 64 # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_CONTEXT_SIZE 64 # define _LIBUNWIND_CURSOR_SIZE 76 # else # error "Unsupported RISC-V ABI" # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV # else # error "Unsupported architecture." # endif #else // !_LIBUNWIND_IS_NATIVE_ONLY # define _LIBUNWIND_TARGET_I386 # define _LIBUNWIND_TARGET_X86_64 1 # define _LIBUNWIND_TARGET_PPC 1 # define _LIBUNWIND_TARGET_PPC64 1 # define _LIBUNWIND_TARGET_AARCH64 1 # define _LIBUNWIND_TARGET_ARM 1 # define _LIBUNWIND_TARGET_OR1K 1 # define _LIBUNWIND_TARGET_MIPS_O32 1 # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 # define _LIBUNWIND_TARGET_SPARC 1 # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_CONTEXT_SIZE 167 # define _LIBUNWIND_CURSOR_SIZE 179 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 #endif // _LIBUNWIND_IS_NATIVE_ONLY #endif // ____LIBUNWIND_CONFIG_H__ Index: projects/clang1000-import/contrib/llvm-project/libunwind/include/libunwind.h =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/include/libunwind.h (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/include/libunwind.h (revision 357209) @@ -1,977 +1,906 @@ //===---------------------------- libunwind.h -----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // // Compatible with libunwind API documented at: // http://www.nongnu.org/libunwind/man/libunwind(3).html // //===----------------------------------------------------------------------===// #ifndef __LIBUNWIND__ #define __LIBUNWIND__ #include <__libunwind_config.h> #include #include #ifdef __APPLE__ #if __clang__ #if __has_include() #include #endif #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 #include #endif #ifdef __arm__ #define LIBUNWIND_AVAIL __attribute__((unavailable)) #elif defined(__OSX_AVAILABLE_STARTING) #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) #else #include #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER #else #define LIBUNWIND_AVAIL __attribute__((unavailable)) #endif #endif #else #define LIBUNWIND_AVAIL #endif /* error codes */ enum { UNW_ESUCCESS = 0, /* no error */ UNW_EUNSPEC = -6540, /* unspecified (general) error */ UNW_ENOMEM = -6541, /* out of memory */ UNW_EBADREG = -6542, /* bad register number */ UNW_EREADONLYREG = -6543, /* attempt to write read-only register */ UNW_ESTOPUNWIND = -6544, /* stop unwinding */ UNW_EINVALIDIP = -6545, /* invalid IP */ UNW_EBADFRAME = -6546, /* bad frame */ UNW_EINVAL = -6547, /* unsupported operation or bad value */ UNW_EBADVERSION = -6548, /* unwind info has unsupported version */ UNW_ENOINFO = -6549 /* no unwind info found */ #if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY) , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */ #endif }; struct unw_context_t { uint64_t data[_LIBUNWIND_CONTEXT_SIZE]; }; typedef struct unw_context_t unw_context_t; struct unw_cursor_t { uint64_t data[_LIBUNWIND_CURSOR_SIZE]; }; typedef struct unw_cursor_t unw_cursor_t; typedef struct unw_addr_space *unw_addr_space_t; typedef int unw_regnum_t; typedef uintptr_t unw_word_t; #if defined(__arm__) && !defined(__ARM_DWARF_EH__) typedef uint64_t unw_fpreg_t; #else 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; #ifdef __cplusplus extern "C" { #endif extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL; 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_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; #ifdef __arm__ /* Save VFP registers in FSTMX format (instead of FSTMD). */ extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL; #endif extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; 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 unw_addr_space_t unw_local_addr_space; #ifdef __cplusplus } #endif // architecture independent register numbers enum { UNW_REG_IP = -1, // instruction pointer UNW_REG_SP = -2, // stack pointer }; // 32-bit x86 registers enum { UNW_X86_EAX = 0, UNW_X86_ECX = 1, UNW_X86_EDX = 2, UNW_X86_EBX = 3, UNW_X86_EBP = 4, UNW_X86_ESP = 5, UNW_X86_ESI = 6, UNW_X86_EDI = 7 }; // 64-bit x86_64 registers enum { UNW_X86_64_RAX = 0, UNW_X86_64_RDX = 1, UNW_X86_64_RCX = 2, UNW_X86_64_RBX = 3, UNW_X86_64_RSI = 4, UNW_X86_64_RDI = 5, UNW_X86_64_RBP = 6, UNW_X86_64_RSP = 7, UNW_X86_64_R8 = 8, UNW_X86_64_R9 = 9, UNW_X86_64_R10 = 10, UNW_X86_64_R11 = 11, UNW_X86_64_R12 = 12, UNW_X86_64_R13 = 13, UNW_X86_64_R14 = 14, UNW_X86_64_R15 = 15, UNW_X86_64_RIP = 16, UNW_X86_64_XMM0 = 17, UNW_X86_64_XMM1 = 18, UNW_X86_64_XMM2 = 19, UNW_X86_64_XMM3 = 20, UNW_X86_64_XMM4 = 21, UNW_X86_64_XMM5 = 22, UNW_X86_64_XMM6 = 23, UNW_X86_64_XMM7 = 24, UNW_X86_64_XMM8 = 25, UNW_X86_64_XMM9 = 26, UNW_X86_64_XMM10 = 27, UNW_X86_64_XMM11 = 28, UNW_X86_64_XMM12 = 29, UNW_X86_64_XMM13 = 30, UNW_X86_64_XMM14 = 31, UNW_X86_64_XMM15 = 32, }; // 32-bit ppc register numbers enum { UNW_PPC_R0 = 0, UNW_PPC_R1 = 1, UNW_PPC_R2 = 2, UNW_PPC_R3 = 3, UNW_PPC_R4 = 4, UNW_PPC_R5 = 5, UNW_PPC_R6 = 6, UNW_PPC_R7 = 7, UNW_PPC_R8 = 8, UNW_PPC_R9 = 9, UNW_PPC_R10 = 10, UNW_PPC_R11 = 11, UNW_PPC_R12 = 12, UNW_PPC_R13 = 13, UNW_PPC_R14 = 14, UNW_PPC_R15 = 15, UNW_PPC_R16 = 16, UNW_PPC_R17 = 17, UNW_PPC_R18 = 18, UNW_PPC_R19 = 19, UNW_PPC_R20 = 20, UNW_PPC_R21 = 21, UNW_PPC_R22 = 22, UNW_PPC_R23 = 23, UNW_PPC_R24 = 24, UNW_PPC_R25 = 25, UNW_PPC_R26 = 26, UNW_PPC_R27 = 27, UNW_PPC_R28 = 28, UNW_PPC_R29 = 29, UNW_PPC_R30 = 30, UNW_PPC_R31 = 31, UNW_PPC_F0 = 32, UNW_PPC_F1 = 33, UNW_PPC_F2 = 34, UNW_PPC_F3 = 35, UNW_PPC_F4 = 36, UNW_PPC_F5 = 37, UNW_PPC_F6 = 38, UNW_PPC_F7 = 39, UNW_PPC_F8 = 40, UNW_PPC_F9 = 41, UNW_PPC_F10 = 42, UNW_PPC_F11 = 43, UNW_PPC_F12 = 44, UNW_PPC_F13 = 45, UNW_PPC_F14 = 46, UNW_PPC_F15 = 47, UNW_PPC_F16 = 48, UNW_PPC_F17 = 49, UNW_PPC_F18 = 50, UNW_PPC_F19 = 51, UNW_PPC_F20 = 52, UNW_PPC_F21 = 53, UNW_PPC_F22 = 54, UNW_PPC_F23 = 55, UNW_PPC_F24 = 56, UNW_PPC_F25 = 57, UNW_PPC_F26 = 58, UNW_PPC_F27 = 59, UNW_PPC_F28 = 60, UNW_PPC_F29 = 61, UNW_PPC_F30 = 62, UNW_PPC_F31 = 63, UNW_PPC_MQ = 64, UNW_PPC_LR = 65, UNW_PPC_CTR = 66, UNW_PPC_AP = 67, UNW_PPC_CR0 = 68, UNW_PPC_CR1 = 69, UNW_PPC_CR2 = 70, UNW_PPC_CR3 = 71, UNW_PPC_CR4 = 72, UNW_PPC_CR5 = 73, UNW_PPC_CR6 = 74, UNW_PPC_CR7 = 75, UNW_PPC_XER = 76, UNW_PPC_V0 = 77, UNW_PPC_V1 = 78, UNW_PPC_V2 = 79, UNW_PPC_V3 = 80, UNW_PPC_V4 = 81, UNW_PPC_V5 = 82, UNW_PPC_V6 = 83, UNW_PPC_V7 = 84, UNW_PPC_V8 = 85, UNW_PPC_V9 = 86, UNW_PPC_V10 = 87, UNW_PPC_V11 = 88, UNW_PPC_V12 = 89, UNW_PPC_V13 = 90, UNW_PPC_V14 = 91, UNW_PPC_V15 = 92, UNW_PPC_V16 = 93, UNW_PPC_V17 = 94, UNW_PPC_V18 = 95, UNW_PPC_V19 = 96, UNW_PPC_V20 = 97, UNW_PPC_V21 = 98, UNW_PPC_V22 = 99, UNW_PPC_V23 = 100, UNW_PPC_V24 = 101, UNW_PPC_V25 = 102, UNW_PPC_V26 = 103, UNW_PPC_V27 = 104, UNW_PPC_V28 = 105, UNW_PPC_V29 = 106, UNW_PPC_V30 = 107, UNW_PPC_V31 = 108, UNW_PPC_VRSAVE = 109, UNW_PPC_VSCR = 110, UNW_PPC_SPE_ACC = 111, UNW_PPC_SPEFSCR = 112 }; // 64-bit ppc register numbers enum { UNW_PPC64_R0 = 0, UNW_PPC64_R1 = 1, UNW_PPC64_R2 = 2, UNW_PPC64_R3 = 3, UNW_PPC64_R4 = 4, UNW_PPC64_R5 = 5, UNW_PPC64_R6 = 6, UNW_PPC64_R7 = 7, UNW_PPC64_R8 = 8, UNW_PPC64_R9 = 9, UNW_PPC64_R10 = 10, UNW_PPC64_R11 = 11, UNW_PPC64_R12 = 12, UNW_PPC64_R13 = 13, UNW_PPC64_R14 = 14, UNW_PPC64_R15 = 15, UNW_PPC64_R16 = 16, UNW_PPC64_R17 = 17, UNW_PPC64_R18 = 18, UNW_PPC64_R19 = 19, UNW_PPC64_R20 = 20, UNW_PPC64_R21 = 21, UNW_PPC64_R22 = 22, UNW_PPC64_R23 = 23, UNW_PPC64_R24 = 24, UNW_PPC64_R25 = 25, UNW_PPC64_R26 = 26, UNW_PPC64_R27 = 27, UNW_PPC64_R28 = 28, UNW_PPC64_R29 = 29, UNW_PPC64_R30 = 30, UNW_PPC64_R31 = 31, UNW_PPC64_F0 = 32, UNW_PPC64_F1 = 33, UNW_PPC64_F2 = 34, UNW_PPC64_F3 = 35, UNW_PPC64_F4 = 36, UNW_PPC64_F5 = 37, UNW_PPC64_F6 = 38, UNW_PPC64_F7 = 39, UNW_PPC64_F8 = 40, UNW_PPC64_F9 = 41, UNW_PPC64_F10 = 42, UNW_PPC64_F11 = 43, UNW_PPC64_F12 = 44, UNW_PPC64_F13 = 45, UNW_PPC64_F14 = 46, UNW_PPC64_F15 = 47, UNW_PPC64_F16 = 48, UNW_PPC64_F17 = 49, UNW_PPC64_F18 = 50, UNW_PPC64_F19 = 51, UNW_PPC64_F20 = 52, UNW_PPC64_F21 = 53, UNW_PPC64_F22 = 54, UNW_PPC64_F23 = 55, UNW_PPC64_F24 = 56, UNW_PPC64_F25 = 57, UNW_PPC64_F26 = 58, UNW_PPC64_F27 = 59, UNW_PPC64_F28 = 60, UNW_PPC64_F29 = 61, UNW_PPC64_F30 = 62, UNW_PPC64_F31 = 63, // 64: reserved UNW_PPC64_LR = 65, UNW_PPC64_CTR = 66, // 67: reserved UNW_PPC64_CR0 = 68, UNW_PPC64_CR1 = 69, UNW_PPC64_CR2 = 70, UNW_PPC64_CR3 = 71, UNW_PPC64_CR4 = 72, UNW_PPC64_CR5 = 73, UNW_PPC64_CR6 = 74, UNW_PPC64_CR7 = 75, UNW_PPC64_XER = 76, UNW_PPC64_V0 = 77, UNW_PPC64_V1 = 78, UNW_PPC64_V2 = 79, UNW_PPC64_V3 = 80, UNW_PPC64_V4 = 81, UNW_PPC64_V5 = 82, UNW_PPC64_V6 = 83, UNW_PPC64_V7 = 84, UNW_PPC64_V8 = 85, UNW_PPC64_V9 = 86, UNW_PPC64_V10 = 87, UNW_PPC64_V11 = 88, UNW_PPC64_V12 = 89, UNW_PPC64_V13 = 90, UNW_PPC64_V14 = 91, UNW_PPC64_V15 = 92, UNW_PPC64_V16 = 93, UNW_PPC64_V17 = 94, UNW_PPC64_V18 = 95, UNW_PPC64_V19 = 96, UNW_PPC64_V20 = 97, UNW_PPC64_V21 = 98, UNW_PPC64_V22 = 99, UNW_PPC64_V23 = 100, UNW_PPC64_V24 = 101, UNW_PPC64_V25 = 102, UNW_PPC64_V26 = 103, UNW_PPC64_V27 = 104, UNW_PPC64_V28 = 105, UNW_PPC64_V29 = 106, UNW_PPC64_V30 = 107, UNW_PPC64_V31 = 108, // 109, 111-113: OpenPOWER ELF V2 ABI: reserved // Borrowing VRSAVE number from PPC32. UNW_PPC64_VRSAVE = 109, UNW_PPC64_VSCR = 110, UNW_PPC64_TFHAR = 114, UNW_PPC64_TFIAR = 115, UNW_PPC64_TEXASR = 116, UNW_PPC64_VS0 = UNW_PPC64_F0, UNW_PPC64_VS1 = UNW_PPC64_F1, UNW_PPC64_VS2 = UNW_PPC64_F2, UNW_PPC64_VS3 = UNW_PPC64_F3, UNW_PPC64_VS4 = UNW_PPC64_F4, UNW_PPC64_VS5 = UNW_PPC64_F5, UNW_PPC64_VS6 = UNW_PPC64_F6, UNW_PPC64_VS7 = UNW_PPC64_F7, UNW_PPC64_VS8 = UNW_PPC64_F8, UNW_PPC64_VS9 = UNW_PPC64_F9, UNW_PPC64_VS10 = UNW_PPC64_F10, UNW_PPC64_VS11 = UNW_PPC64_F11, UNW_PPC64_VS12 = UNW_PPC64_F12, UNW_PPC64_VS13 = UNW_PPC64_F13, UNW_PPC64_VS14 = UNW_PPC64_F14, UNW_PPC64_VS15 = UNW_PPC64_F15, UNW_PPC64_VS16 = UNW_PPC64_F16, UNW_PPC64_VS17 = UNW_PPC64_F17, UNW_PPC64_VS18 = UNW_PPC64_F18, UNW_PPC64_VS19 = UNW_PPC64_F19, UNW_PPC64_VS20 = UNW_PPC64_F20, UNW_PPC64_VS21 = UNW_PPC64_F21, UNW_PPC64_VS22 = UNW_PPC64_F22, UNW_PPC64_VS23 = UNW_PPC64_F23, UNW_PPC64_VS24 = UNW_PPC64_F24, UNW_PPC64_VS25 = UNW_PPC64_F25, UNW_PPC64_VS26 = UNW_PPC64_F26, UNW_PPC64_VS27 = UNW_PPC64_F27, UNW_PPC64_VS28 = UNW_PPC64_F28, UNW_PPC64_VS29 = UNW_PPC64_F29, UNW_PPC64_VS30 = UNW_PPC64_F30, UNW_PPC64_VS31 = UNW_PPC64_F31, UNW_PPC64_VS32 = UNW_PPC64_V0, UNW_PPC64_VS33 = UNW_PPC64_V1, UNW_PPC64_VS34 = UNW_PPC64_V2, UNW_PPC64_VS35 = UNW_PPC64_V3, UNW_PPC64_VS36 = UNW_PPC64_V4, UNW_PPC64_VS37 = UNW_PPC64_V5, UNW_PPC64_VS38 = UNW_PPC64_V6, UNW_PPC64_VS39 = UNW_PPC64_V7, UNW_PPC64_VS40 = UNW_PPC64_V8, UNW_PPC64_VS41 = UNW_PPC64_V9, UNW_PPC64_VS42 = UNW_PPC64_V10, UNW_PPC64_VS43 = UNW_PPC64_V11, UNW_PPC64_VS44 = UNW_PPC64_V12, UNW_PPC64_VS45 = UNW_PPC64_V13, UNW_PPC64_VS46 = UNW_PPC64_V14, UNW_PPC64_VS47 = UNW_PPC64_V15, UNW_PPC64_VS48 = UNW_PPC64_V16, UNW_PPC64_VS49 = UNW_PPC64_V17, UNW_PPC64_VS50 = UNW_PPC64_V18, UNW_PPC64_VS51 = UNW_PPC64_V19, UNW_PPC64_VS52 = UNW_PPC64_V20, UNW_PPC64_VS53 = UNW_PPC64_V21, UNW_PPC64_VS54 = UNW_PPC64_V22, UNW_PPC64_VS55 = UNW_PPC64_V23, UNW_PPC64_VS56 = UNW_PPC64_V24, UNW_PPC64_VS57 = UNW_PPC64_V25, UNW_PPC64_VS58 = UNW_PPC64_V26, UNW_PPC64_VS59 = UNW_PPC64_V27, UNW_PPC64_VS60 = UNW_PPC64_V28, UNW_PPC64_VS61 = UNW_PPC64_V29, UNW_PPC64_VS62 = UNW_PPC64_V30, UNW_PPC64_VS63 = UNW_PPC64_V31 }; // 64-bit ARM64 registers enum { UNW_ARM64_X0 = 0, UNW_ARM64_X1 = 1, UNW_ARM64_X2 = 2, UNW_ARM64_X3 = 3, UNW_ARM64_X4 = 4, UNW_ARM64_X5 = 5, UNW_ARM64_X6 = 6, UNW_ARM64_X7 = 7, UNW_ARM64_X8 = 8, UNW_ARM64_X9 = 9, UNW_ARM64_X10 = 10, UNW_ARM64_X11 = 11, UNW_ARM64_X12 = 12, UNW_ARM64_X13 = 13, UNW_ARM64_X14 = 14, UNW_ARM64_X15 = 15, UNW_ARM64_X16 = 16, UNW_ARM64_X17 = 17, UNW_ARM64_X18 = 18, UNW_ARM64_X19 = 19, UNW_ARM64_X20 = 20, UNW_ARM64_X21 = 21, UNW_ARM64_X22 = 22, UNW_ARM64_X23 = 23, UNW_ARM64_X24 = 24, UNW_ARM64_X25 = 25, UNW_ARM64_X26 = 26, UNW_ARM64_X27 = 27, UNW_ARM64_X28 = 28, UNW_ARM64_X29 = 29, UNW_ARM64_FP = 29, UNW_ARM64_X30 = 30, UNW_ARM64_LR = 30, UNW_ARM64_X31 = 31, UNW_ARM64_SP = 31, // reserved block UNW_ARM64_RA_SIGN_STATE = 34, // reserved block UNW_ARM64_D0 = 64, UNW_ARM64_D1 = 65, UNW_ARM64_D2 = 66, UNW_ARM64_D3 = 67, UNW_ARM64_D4 = 68, UNW_ARM64_D5 = 69, UNW_ARM64_D6 = 70, UNW_ARM64_D7 = 71, UNW_ARM64_D8 = 72, UNW_ARM64_D9 = 73, UNW_ARM64_D10 = 74, UNW_ARM64_D11 = 75, UNW_ARM64_D12 = 76, UNW_ARM64_D13 = 77, UNW_ARM64_D14 = 78, UNW_ARM64_D15 = 79, UNW_ARM64_D16 = 80, UNW_ARM64_D17 = 81, UNW_ARM64_D18 = 82, UNW_ARM64_D19 = 83, UNW_ARM64_D20 = 84, UNW_ARM64_D21 = 85, UNW_ARM64_D22 = 86, UNW_ARM64_D23 = 87, UNW_ARM64_D24 = 88, UNW_ARM64_D25 = 89, UNW_ARM64_D26 = 90, UNW_ARM64_D27 = 91, UNW_ARM64_D28 = 92, UNW_ARM64_D29 = 93, UNW_ARM64_D30 = 94, UNW_ARM64_D31 = 95, }; // 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1. // Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3. // In this scheme, even though the 64-bit floating point registers D0-D31 // overlap physically with the 32-bit floating pointer registers S0-S31, // they are given a non-overlapping range of register numbers. // // Commented out ranges are not preserved during unwinding. enum { UNW_ARM_R0 = 0, UNW_ARM_R1 = 1, UNW_ARM_R2 = 2, UNW_ARM_R3 = 3, UNW_ARM_R4 = 4, UNW_ARM_R5 = 5, UNW_ARM_R6 = 6, UNW_ARM_R7 = 7, UNW_ARM_R8 = 8, UNW_ARM_R9 = 9, UNW_ARM_R10 = 10, UNW_ARM_R11 = 11, UNW_ARM_R12 = 12, UNW_ARM_SP = 13, // Logical alias for UNW_REG_SP UNW_ARM_R13 = 13, UNW_ARM_LR = 14, UNW_ARM_R14 = 14, UNW_ARM_IP = 15, // Logical alias for UNW_REG_IP UNW_ARM_R15 = 15, // 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31. UNW_ARM_S0 = 64, UNW_ARM_S1 = 65, UNW_ARM_S2 = 66, UNW_ARM_S3 = 67, UNW_ARM_S4 = 68, UNW_ARM_S5 = 69, UNW_ARM_S6 = 70, UNW_ARM_S7 = 71, UNW_ARM_S8 = 72, UNW_ARM_S9 = 73, UNW_ARM_S10 = 74, UNW_ARM_S11 = 75, UNW_ARM_S12 = 76, UNW_ARM_S13 = 77, UNW_ARM_S14 = 78, UNW_ARM_S15 = 79, UNW_ARM_S16 = 80, UNW_ARM_S17 = 81, UNW_ARM_S18 = 82, UNW_ARM_S19 = 83, UNW_ARM_S20 = 84, UNW_ARM_S21 = 85, UNW_ARM_S22 = 86, UNW_ARM_S23 = 87, UNW_ARM_S24 = 88, UNW_ARM_S25 = 89, UNW_ARM_S26 = 90, UNW_ARM_S27 = 91, UNW_ARM_S28 = 92, UNW_ARM_S29 = 93, UNW_ARM_S30 = 94, UNW_ARM_S31 = 95, // 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP. // 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX) UNW_ARM_WR0 = 112, UNW_ARM_WR1 = 113, UNW_ARM_WR2 = 114, UNW_ARM_WR3 = 115, UNW_ARM_WR4 = 116, UNW_ARM_WR5 = 117, UNW_ARM_WR6 = 118, UNW_ARM_WR7 = 119, UNW_ARM_WR8 = 120, UNW_ARM_WR9 = 121, UNW_ARM_WR10 = 122, UNW_ARM_WR11 = 123, UNW_ARM_WR12 = 124, UNW_ARM_WR13 = 125, UNW_ARM_WR14 = 126, UNW_ARM_WR15 = 127, // 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC} // 134-143 -- Reserved // 144-150 -- R8_USR-R14_USR // 151-157 -- R8_FIQ-R14_FIQ // 158-159 -- R13_IRQ-R14_IRQ // 160-161 -- R13_ABT-R14_ABT // 162-163 -- R13_UND-R14_UND // 164-165 -- R13_SVC-R14_SVC // 166-191 -- Reserved UNW_ARM_WC0 = 192, UNW_ARM_WC1 = 193, UNW_ARM_WC2 = 194, UNW_ARM_WC3 = 195, // 196-199 -- wC4-wC7 (Intel wireless MMX control) // 200-255 -- Reserved UNW_ARM_D0 = 256, UNW_ARM_D1 = 257, UNW_ARM_D2 = 258, UNW_ARM_D3 = 259, UNW_ARM_D4 = 260, UNW_ARM_D5 = 261, UNW_ARM_D6 = 262, UNW_ARM_D7 = 263, UNW_ARM_D8 = 264, UNW_ARM_D9 = 265, UNW_ARM_D10 = 266, UNW_ARM_D11 = 267, UNW_ARM_D12 = 268, UNW_ARM_D13 = 269, UNW_ARM_D14 = 270, UNW_ARM_D15 = 271, UNW_ARM_D16 = 272, UNW_ARM_D17 = 273, UNW_ARM_D18 = 274, UNW_ARM_D19 = 275, UNW_ARM_D20 = 276, UNW_ARM_D21 = 277, UNW_ARM_D22 = 278, UNW_ARM_D23 = 279, UNW_ARM_D24 = 280, UNW_ARM_D25 = 281, UNW_ARM_D26 = 282, UNW_ARM_D27 = 283, UNW_ARM_D28 = 284, UNW_ARM_D29 = 285, UNW_ARM_D30 = 286, UNW_ARM_D31 = 287, // 288-319 -- Reserved for VFP/Neon // 320-8191 -- Reserved // 8192-16383 -- Unspecified vendor co-processor register. }; // OpenRISC1000 register numbers enum { UNW_OR1K_R0 = 0, UNW_OR1K_R1 = 1, UNW_OR1K_R2 = 2, UNW_OR1K_R3 = 3, UNW_OR1K_R4 = 4, UNW_OR1K_R5 = 5, UNW_OR1K_R6 = 6, UNW_OR1K_R7 = 7, UNW_OR1K_R8 = 8, UNW_OR1K_R9 = 9, UNW_OR1K_R10 = 10, UNW_OR1K_R11 = 11, UNW_OR1K_R12 = 12, UNW_OR1K_R13 = 13, UNW_OR1K_R14 = 14, UNW_OR1K_R15 = 15, UNW_OR1K_R16 = 16, UNW_OR1K_R17 = 17, UNW_OR1K_R18 = 18, UNW_OR1K_R19 = 19, UNW_OR1K_R20 = 20, UNW_OR1K_R21 = 21, UNW_OR1K_R22 = 22, UNW_OR1K_R23 = 23, UNW_OR1K_R24 = 24, UNW_OR1K_R25 = 25, UNW_OR1K_R26 = 26, UNW_OR1K_R27 = 27, UNW_OR1K_R28 = 28, UNW_OR1K_R29 = 29, UNW_OR1K_R30 = 30, UNW_OR1K_R31 = 31, UNW_OR1K_EPCR = 32, }; -// 64-bit RISC-V registers -enum { - UNW_RISCV_X0 = 0, - UNW_RISCV_X1 = 1, - UNW_RISCV_RA = 1, - UNW_RISCV_X2 = 2, - UNW_RISCV_SP = 2, - UNW_RISCV_X3 = 3, - UNW_RISCV_X4 = 4, - UNW_RISCV_X5 = 5, - UNW_RISCV_X6 = 6, - UNW_RISCV_X7 = 7, - UNW_RISCV_X8 = 8, - UNW_RISCV_X9 = 9, - UNW_RISCV_X10 = 10, - UNW_RISCV_X11 = 11, - UNW_RISCV_X12 = 12, - UNW_RISCV_X13 = 13, - UNW_RISCV_X14 = 14, - UNW_RISCV_X15 = 15, - UNW_RISCV_X16 = 16, - UNW_RISCV_X17 = 17, - UNW_RISCV_X18 = 18, - UNW_RISCV_X19 = 19, - UNW_RISCV_X20 = 20, - UNW_RISCV_X21 = 21, - UNW_RISCV_X22 = 22, - UNW_RISCV_X23 = 23, - UNW_RISCV_X24 = 24, - UNW_RISCV_X25 = 25, - UNW_RISCV_X26 = 26, - UNW_RISCV_X27 = 27, - UNW_RISCV_X28 = 28, - UNW_RISCV_X29 = 29, - UNW_RISCV_X30 = 30, - UNW_RISCV_X31 = 31, - // reserved block - UNW_RISCV_D0 = 64, - UNW_RISCV_D1 = 65, - UNW_RISCV_D2 = 66, - UNW_RISCV_D3 = 67, - UNW_RISCV_D4 = 68, - UNW_RISCV_D5 = 69, - UNW_RISCV_D6 = 70, - UNW_RISCV_D7 = 71, - UNW_RISCV_D8 = 72, - UNW_RISCV_D9 = 73, - UNW_RISCV_D10 = 74, - UNW_RISCV_D11 = 75, - UNW_RISCV_D12 = 76, - UNW_RISCV_D13 = 77, - UNW_RISCV_D14 = 78, - UNW_RISCV_D15 = 79, - UNW_RISCV_D16 = 80, - UNW_RISCV_D17 = 81, - UNW_RISCV_D18 = 82, - UNW_RISCV_D19 = 83, - UNW_RISCV_D20 = 84, - UNW_RISCV_D21 = 85, - UNW_RISCV_D22 = 86, - UNW_RISCV_D23 = 87, - UNW_RISCV_D24 = 88, - UNW_RISCV_D25 = 89, - UNW_RISCV_D26 = 90, - UNW_RISCV_D27 = 91, - UNW_RISCV_D28 = 92, - UNW_RISCV_D29 = 93, - UNW_RISCV_D30 = 94, - UNW_RISCV_D31 = 95, -}; - // MIPS registers enum { UNW_MIPS_R0 = 0, UNW_MIPS_R1 = 1, UNW_MIPS_R2 = 2, UNW_MIPS_R3 = 3, UNW_MIPS_R4 = 4, UNW_MIPS_R5 = 5, UNW_MIPS_R6 = 6, UNW_MIPS_R7 = 7, UNW_MIPS_R8 = 8, UNW_MIPS_R9 = 9, UNW_MIPS_R10 = 10, UNW_MIPS_R11 = 11, UNW_MIPS_R12 = 12, UNW_MIPS_R13 = 13, UNW_MIPS_R14 = 14, UNW_MIPS_R15 = 15, UNW_MIPS_R16 = 16, UNW_MIPS_R17 = 17, UNW_MIPS_R18 = 18, UNW_MIPS_R19 = 19, UNW_MIPS_R20 = 20, UNW_MIPS_R21 = 21, UNW_MIPS_R22 = 22, UNW_MIPS_R23 = 23, UNW_MIPS_R24 = 24, UNW_MIPS_R25 = 25, UNW_MIPS_R26 = 26, UNW_MIPS_R27 = 27, UNW_MIPS_R28 = 28, UNW_MIPS_R29 = 29, UNW_MIPS_R30 = 30, UNW_MIPS_R31 = 31, UNW_MIPS_F0 = 32, UNW_MIPS_F1 = 33, UNW_MIPS_F2 = 34, UNW_MIPS_F3 = 35, UNW_MIPS_F4 = 36, UNW_MIPS_F5 = 37, UNW_MIPS_F6 = 38, UNW_MIPS_F7 = 39, UNW_MIPS_F8 = 40, UNW_MIPS_F9 = 41, UNW_MIPS_F10 = 42, UNW_MIPS_F11 = 43, UNW_MIPS_F12 = 44, UNW_MIPS_F13 = 45, UNW_MIPS_F14 = 46, UNW_MIPS_F15 = 47, UNW_MIPS_F16 = 48, UNW_MIPS_F17 = 49, UNW_MIPS_F18 = 50, UNW_MIPS_F19 = 51, UNW_MIPS_F20 = 52, UNW_MIPS_F21 = 53, UNW_MIPS_F22 = 54, UNW_MIPS_F23 = 55, UNW_MIPS_F24 = 56, UNW_MIPS_F25 = 57, UNW_MIPS_F26 = 58, UNW_MIPS_F27 = 59, UNW_MIPS_F28 = 60, UNW_MIPS_F29 = 61, UNW_MIPS_F30 = 62, UNW_MIPS_F31 = 63, UNW_MIPS_HI = 64, UNW_MIPS_LO = 65, }; // SPARC registers enum { UNW_SPARC_G0 = 0, UNW_SPARC_G1 = 1, UNW_SPARC_G2 = 2, UNW_SPARC_G3 = 3, UNW_SPARC_G4 = 4, UNW_SPARC_G5 = 5, UNW_SPARC_G6 = 6, UNW_SPARC_G7 = 7, UNW_SPARC_O0 = 8, UNW_SPARC_O1 = 9, UNW_SPARC_O2 = 10, UNW_SPARC_O3 = 11, UNW_SPARC_O4 = 12, UNW_SPARC_O5 = 13, UNW_SPARC_O6 = 14, UNW_SPARC_O7 = 15, UNW_SPARC_L0 = 16, UNW_SPARC_L1 = 17, UNW_SPARC_L2 = 18, UNW_SPARC_L3 = 19, UNW_SPARC_L4 = 20, UNW_SPARC_L5 = 21, UNW_SPARC_L6 = 22, UNW_SPARC_L7 = 23, UNW_SPARC_I0 = 24, UNW_SPARC_I1 = 25, UNW_SPARC_I2 = 26, UNW_SPARC_I3 = 27, UNW_SPARC_I4 = 28, UNW_SPARC_I5 = 29, UNW_SPARC_I6 = 30, UNW_SPARC_I7 = 31, }; // RISC-V registers. These match the DWARF register numbers defined by section // 4 of the RISC-V ELF psABI specification, which can be found at: // // https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md enum { UNW_RISCV_X0 = 0, UNW_RISCV_X1 = 1, UNW_RISCV_X2 = 2, UNW_RISCV_X3 = 3, UNW_RISCV_X4 = 4, UNW_RISCV_X5 = 5, UNW_RISCV_X6 = 6, UNW_RISCV_X7 = 7, UNW_RISCV_X8 = 8, UNW_RISCV_X9 = 9, UNW_RISCV_X10 = 10, UNW_RISCV_X11 = 11, UNW_RISCV_X12 = 12, UNW_RISCV_X13 = 13, UNW_RISCV_X14 = 14, UNW_RISCV_X15 = 15, UNW_RISCV_X16 = 16, UNW_RISCV_X17 = 17, UNW_RISCV_X18 = 18, UNW_RISCV_X19 = 19, UNW_RISCV_X20 = 20, UNW_RISCV_X21 = 21, UNW_RISCV_X22 = 22, UNW_RISCV_X23 = 23, UNW_RISCV_X24 = 24, UNW_RISCV_X25 = 25, UNW_RISCV_X26 = 26, UNW_RISCV_X27 = 27, UNW_RISCV_X28 = 28, UNW_RISCV_X29 = 29, UNW_RISCV_X30 = 30, UNW_RISCV_X31 = 31, UNW_RISCV_F0 = 32, UNW_RISCV_F1 = 33, UNW_RISCV_F2 = 34, UNW_RISCV_F3 = 35, UNW_RISCV_F4 = 36, UNW_RISCV_F5 = 37, UNW_RISCV_F6 = 38, UNW_RISCV_F7 = 39, UNW_RISCV_F8 = 40, UNW_RISCV_F9 = 41, UNW_RISCV_F10 = 42, UNW_RISCV_F11 = 43, UNW_RISCV_F12 = 44, UNW_RISCV_F13 = 45, UNW_RISCV_F14 = 46, UNW_RISCV_F15 = 47, UNW_RISCV_F16 = 48, UNW_RISCV_F17 = 49, UNW_RISCV_F18 = 50, UNW_RISCV_F19 = 51, UNW_RISCV_F20 = 52, UNW_RISCV_F21 = 53, UNW_RISCV_F22 = 54, UNW_RISCV_F23 = 55, UNW_RISCV_F24 = 56, UNW_RISCV_F25 = 57, UNW_RISCV_F26 = 58, UNW_RISCV_F27 = 59, UNW_RISCV_F28 = 60, UNW_RISCV_F29 = 61, UNW_RISCV_F30 = 62, UNW_RISCV_F31 = 63, }; #endif Index: projects/clang1000-import/contrib/llvm-project/libunwind/src/Registers.hpp =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/src/Registers.hpp (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/src/Registers.hpp (revision 357209) @@ -1,4049 +1,3787 @@ //===----------------------------- Registers.hpp --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // // Models register sets for supported processors. // //===----------------------------------------------------------------------===// #ifndef __REGISTERS_HPP__ #define __REGISTERS_HPP__ #include #include #include "libunwind.h" #include "config.h" namespace libunwind { // For emulating 128-bit registers struct v128 { uint32_t vec[4]; }; enum { REGISTERS_X86, REGISTERS_X86_64, REGISTERS_PPC, REGISTERS_PPC64, REGISTERS_ARM64, REGISTERS_ARM, REGISTERS_OR1K, - REGISTERS_RISCV, REGISTERS_MIPS_O32, REGISTERS_MIPS_NEWABI, REGISTERS_SPARC, REGISTERS_RISCV, }; #if defined(_LIBUNWIND_TARGET_I386) /// Registers_x86 holds the register state of a thread in a 32-bit intel /// process. class _LIBUNWIND_HIDDEN Registers_x86 { public: Registers_x86(); Registers_x86(const void *registers); bool validRegister(int num) const; uint32_t getRegister(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); bool validVectorRegister(int) const { return false; } v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } static int getArch() { return REGISTERS_X86; } uint32_t getSP() const { return _registers.__esp; } void setSP(uint32_t value) { _registers.__esp = value; } uint32_t getIP() const { return _registers.__eip; } void setIP(uint32_t value) { _registers.__eip = value; } uint32_t getEBP() const { return _registers.__ebp; } void setEBP(uint32_t value) { _registers.__ebp = value; } uint32_t getEBX() const { return _registers.__ebx; } void setEBX(uint32_t value) { _registers.__ebx = value; } uint32_t getECX() const { return _registers.__ecx; } void setECX(uint32_t value) { _registers.__ecx = value; } uint32_t getEDX() const { return _registers.__edx; } void setEDX(uint32_t value) { _registers.__edx = value; } uint32_t getESI() const { return _registers.__esi; } void setESI(uint32_t value) { _registers.__esi = value; } uint32_t getEDI() const { return _registers.__edi; } void setEDI(uint32_t value) { _registers.__edi = value; } private: struct GPRs { 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 __ss; unsigned int __eflags; unsigned int __eip; unsigned int __cs; unsigned int __ds; unsigned int __es; unsigned int __fs; unsigned int __gs; }; GPRs _registers; }; 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)); } inline Registers_x86::Registers_x86() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_x86::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum > 7) return false; return true; } inline uint32_t Registers_x86::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: return _registers.__eip; case UNW_REG_SP: return _registers.__esp; case UNW_X86_EAX: return _registers.__eax; case UNW_X86_ECX: return _registers.__ecx; case UNW_X86_EDX: return _registers.__edx; case UNW_X86_EBX: return _registers.__ebx; #if !defined(__APPLE__) case UNW_X86_ESP: #else case UNW_X86_EBP: #endif return _registers.__ebp; #if !defined(__APPLE__) case UNW_X86_EBP: #else case UNW_X86_ESP: #endif return _registers.__esp; case UNW_X86_ESI: return _registers.__esi; case UNW_X86_EDI: return _registers.__edi; } _LIBUNWIND_ABORT("unsupported x86 register"); } inline void Registers_x86::setRegister(int regNum, uint32_t value) { switch (regNum) { case UNW_REG_IP: _registers.__eip = value; return; case UNW_REG_SP: _registers.__esp = value; return; case UNW_X86_EAX: _registers.__eax = value; return; case UNW_X86_ECX: _registers.__ecx = value; return; case UNW_X86_EDX: _registers.__edx = value; return; case UNW_X86_EBX: _registers.__ebx = value; return; #if !defined(__APPLE__) case UNW_X86_ESP: #else case UNW_X86_EBP: #endif _registers.__ebp = value; return; #if !defined(__APPLE__) case UNW_X86_EBP: #else case UNW_X86_ESP: #endif _registers.__esp = value; return; case UNW_X86_ESI: _registers.__esi = value; return; case UNW_X86_EDI: _registers.__edi = value; return; } _LIBUNWIND_ABORT("unsupported x86 register"); } inline const char *Registers_x86::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "ip"; case UNW_REG_SP: return "esp"; case UNW_X86_EAX: return "eax"; case UNW_X86_ECX: return "ecx"; case UNW_X86_EDX: return "edx"; case UNW_X86_EBX: return "ebx"; case UNW_X86_EBP: return "ebp"; case UNW_X86_ESP: return "esp"; case UNW_X86_ESI: return "esi"; case UNW_X86_EDI: return "edi"; default: return "unknown register"; } } inline double Registers_x86::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86 float registers"); } inline void Registers_x86::setFloatRegister(int, double) { _LIBUNWIND_ABORT("no x86 float registers"); } inline v128 Registers_x86::getVectorRegister(int) const { _LIBUNWIND_ABORT("no x86 vector registers"); } inline void Registers_x86::setVectorRegister(int, v128) { _LIBUNWIND_ABORT("no x86 vector registers"); } #endif // _LIBUNWIND_TARGET_I386 #if defined(_LIBUNWIND_TARGET_X86_64) /// Registers_x86_64 holds the register state of a thread in a 64-bit intel /// process. class _LIBUNWIND_HIDDEN Registers_x86_64 { public: Registers_x86_64(); Registers_x86_64(const void *registers); bool validRegister(int num) const; uint64_t getRegister(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); bool validVectorRegister(int) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } static int getArch() { return REGISTERS_X86_64; } uint64_t getSP() const { return _registers.__rsp; } void setSP(uint64_t value) { _registers.__rsp = value; } uint64_t getIP() const { return _registers.__rip; } void setIP(uint64_t value) { _registers.__rip = value; } uint64_t getRBP() const { return _registers.__rbp; } void setRBP(uint64_t value) { _registers.__rbp = value; } uint64_t getRBX() const { return _registers.__rbx; } void setRBX(uint64_t value) { _registers.__rbx = value; } uint64_t getR12() const { return _registers.__r12; } void setR12(uint64_t value) { _registers.__r12 = value; } uint64_t getR13() const { return _registers.__r13; } void setR13(uint64_t value) { _registers.__r13 = value; } uint64_t getR14() const { return _registers.__r14; } void setR14(uint64_t value) { _registers.__r14 = value; } uint64_t getR15() const { return _registers.__r15; } void setR15(uint64_t value) { _registers.__r15 = value; } private: struct GPRs { 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; uint64_t __rflags; uint64_t __cs; uint64_t __fs; uint64_t __gs; #if defined(_WIN64) uint64_t __padding; // 16-byte align #endif }; GPRs _registers; #if defined(_WIN64) v128 _xmm[16]; #endif }; 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)); } inline Registers_x86_64::Registers_x86_64() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_x86_64::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum > 15) return false; return true; } inline uint64_t Registers_x86_64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: return _registers.__rip; case UNW_REG_SP: return _registers.__rsp; case UNW_X86_64_RAX: return _registers.__rax; case UNW_X86_64_RDX: return _registers.__rdx; case UNW_X86_64_RCX: return _registers.__rcx; case UNW_X86_64_RBX: return _registers.__rbx; case UNW_X86_64_RSI: return _registers.__rsi; case UNW_X86_64_RDI: return _registers.__rdi; case UNW_X86_64_RBP: return _registers.__rbp; case UNW_X86_64_RSP: return _registers.__rsp; case UNW_X86_64_R8: return _registers.__r8; case UNW_X86_64_R9: return _registers.__r9; case UNW_X86_64_R10: return _registers.__r10; case UNW_X86_64_R11: return _registers.__r11; case UNW_X86_64_R12: return _registers.__r12; case UNW_X86_64_R13: return _registers.__r13; case UNW_X86_64_R14: return _registers.__r14; case UNW_X86_64_R15: return _registers.__r15; } _LIBUNWIND_ABORT("unsupported x86_64 register"); } inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: _registers.__rip = value; return; case UNW_REG_SP: _registers.__rsp = value; return; case UNW_X86_64_RAX: _registers.__rax = value; return; case UNW_X86_64_RDX: _registers.__rdx = value; return; case UNW_X86_64_RCX: _registers.__rcx = value; return; case UNW_X86_64_RBX: _registers.__rbx = value; return; case UNW_X86_64_RSI: _registers.__rsi = value; return; case UNW_X86_64_RDI: _registers.__rdi = value; return; case UNW_X86_64_RBP: _registers.__rbp = value; return; case UNW_X86_64_RSP: _registers.__rsp = value; return; case UNW_X86_64_R8: _registers.__r8 = value; return; case UNW_X86_64_R9: _registers.__r9 = value; return; case UNW_X86_64_R10: _registers.__r10 = value; return; case UNW_X86_64_R11: _registers.__r11 = value; return; case UNW_X86_64_R12: _registers.__r12 = value; return; case UNW_X86_64_R13: _registers.__r13 = value; return; case UNW_X86_64_R14: _registers.__r14 = value; return; case UNW_X86_64_R15: _registers.__r15 = value; return; } _LIBUNWIND_ABORT("unsupported x86_64 register"); } inline const char *Registers_x86_64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "rip"; case UNW_REG_SP: return "rsp"; case UNW_X86_64_RAX: return "rax"; case UNW_X86_64_RDX: return "rdx"; case UNW_X86_64_RCX: return "rcx"; case UNW_X86_64_RBX: return "rbx"; case UNW_X86_64_RSI: return "rsi"; case UNW_X86_64_RDI: return "rdi"; case UNW_X86_64_RBP: return "rbp"; case UNW_X86_64_RSP: return "rsp"; case UNW_X86_64_R8: return "r8"; case UNW_X86_64_R9: return "r9"; case UNW_X86_64_R10: return "r10"; case UNW_X86_64_R11: return "r11"; case UNW_X86_64_R12: return "r12"; case UNW_X86_64_R13: return "r13"; case UNW_X86_64_R14: return "r14"; case UNW_X86_64_R15: return "r15"; case UNW_X86_64_XMM0: return "xmm0"; case UNW_X86_64_XMM1: return "xmm1"; case UNW_X86_64_XMM2: return "xmm2"; case UNW_X86_64_XMM3: return "xmm3"; case UNW_X86_64_XMM4: return "xmm4"; case UNW_X86_64_XMM5: return "xmm5"; case UNW_X86_64_XMM6: return "xmm6"; case UNW_X86_64_XMM7: return "xmm7"; case UNW_X86_64_XMM8: return "xmm8"; case UNW_X86_64_XMM9: return "xmm9"; case UNW_X86_64_XMM10: return "xmm10"; case UNW_X86_64_XMM11: return "xmm11"; case UNW_X86_64_XMM12: return "xmm12"; case UNW_X86_64_XMM13: return "xmm13"; case UNW_X86_64_XMM14: return "xmm14"; case UNW_X86_64_XMM15: return "xmm15"; default: return "unknown register"; } } inline double Registers_x86_64::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86_64 float registers"); } inline void Registers_x86_64::setFloatRegister(int, double) { _LIBUNWIND_ABORT("no x86_64 float registers"); } inline bool Registers_x86_64::validVectorRegister(int regNum) const { #if defined(_WIN64) if (regNum < UNW_X86_64_XMM0) return false; if (regNum > UNW_X86_64_XMM15) return false; return true; #else (void)regNum; // suppress unused parameter warning return false; #endif } inline v128 Registers_x86_64::getVectorRegister(int regNum) const { #if defined(_WIN64) assert(validVectorRegister(regNum)); return _xmm[regNum - UNW_X86_64_XMM0]; #else (void)regNum; // suppress unused parameter warning _LIBUNWIND_ABORT("no x86_64 vector registers"); #endif } inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { #if defined(_WIN64) assert(validVectorRegister(regNum)); _xmm[regNum - UNW_X86_64_XMM0] = value; #else (void)regNum; (void)value; // suppress unused parameter warnings _LIBUNWIND_ABORT("no x86_64 vector registers"); #endif } #endif // _LIBUNWIND_TARGET_X86_64 #if defined(_LIBUNWIND_TARGET_PPC) /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC /// process. class _LIBUNWIND_HIDDEN Registers_ppc { public: Registers_ppc(); Registers_ppc(const void *registers); bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } static int getArch() { return REGISTERS_PPC; } uint64_t getSP() const { return _registers.__r1; } void setSP(uint32_t value) { _registers.__r1 = value; } uint64_t getIP() const { return _registers.__srr0; } void setIP(uint32_t value) { _registers.__srr0 = value; } private: struct ppc_thread_state_t { unsigned int __srr0; /* Instruction address register (PC) */ unsigned int __srr1; /* Machine state register (supervisor) */ unsigned int __r0; unsigned int __r1; unsigned int __r2; unsigned int __r3; unsigned int __r4; unsigned int __r5; unsigned int __r6; unsigned int __r7; unsigned int __r8; unsigned int __r9; unsigned int __r10; unsigned int __r11; unsigned int __r12; unsigned int __r13; unsigned int __r14; unsigned int __r15; unsigned int __r16; unsigned int __r17; unsigned int __r18; unsigned int __r19; unsigned int __r20; unsigned int __r21; unsigned int __r22; unsigned int __r23; unsigned int __r24; unsigned int __r25; unsigned int __r26; unsigned int __r27; unsigned int __r28; unsigned int __r29; unsigned int __r30; unsigned int __r31; unsigned int __cr; /* Condition register */ unsigned int __xer; /* User's integer exception register */ unsigned int __lr; /* Link register */ unsigned int __ctr; /* Count register */ unsigned int __mq; /* MQ register (601 only) */ unsigned int __vrsave; /* Vector Save Register */ }; struct ppc_float_state_t { double __fpregs[32]; unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ unsigned int __fpscr; /* floating point status register */ }; ppc_thread_state_t _registers; ppc_float_state_t _floatRegisters; v128 _vectorRegisters[32]; // offset 424 }; inline Registers_ppc::Registers_ppc(const void *registers) { static_assert((check_fit::does_fit), "ppc registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); static_assert(sizeof(ppc_thread_state_t) == 160, "expected float register offset to be 160"); memcpy(&_floatRegisters, static_cast(registers) + sizeof(ppc_thread_state_t), sizeof(_floatRegisters)); static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424, "expected vector register offset to be 424 bytes"); memcpy(_vectorRegisters, static_cast(registers) + sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t), sizeof(_vectorRegisters)); } inline Registers_ppc::Registers_ppc() { memset(&_registers, 0, sizeof(_registers)); memset(&_floatRegisters, 0, sizeof(_floatRegisters)); memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); } inline bool Registers_ppc::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum == UNW_PPC_VRSAVE) return true; if (regNum < 0) return false; if (regNum <= UNW_PPC_R31) return true; if (regNum == UNW_PPC_MQ) return true; if (regNum == UNW_PPC_LR) return true; if (regNum == UNW_PPC_CTR) return true; if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7)) return true; return false; } inline uint32_t Registers_ppc::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: return _registers.__srr0; case UNW_REG_SP: return _registers.__r1; case UNW_PPC_R0: return _registers.__r0; case UNW_PPC_R1: return _registers.__r1; case UNW_PPC_R2: return _registers.__r2; case UNW_PPC_R3: return _registers.__r3; case UNW_PPC_R4: return _registers.__r4; case UNW_PPC_R5: return _registers.__r5; case UNW_PPC_R6: return _registers.__r6; case UNW_PPC_R7: return _registers.__r7; case UNW_PPC_R8: return _registers.__r8; case UNW_PPC_R9: return _registers.__r9; case UNW_PPC_R10: return _registers.__r10; case UNW_PPC_R11: return _registers.__r11; case UNW_PPC_R12: return _registers.__r12; case UNW_PPC_R13: return _registers.__r13; case UNW_PPC_R14: return _registers.__r14; case UNW_PPC_R15: return _registers.__r15; case UNW_PPC_R16: return _registers.__r16; case UNW_PPC_R17: return _registers.__r17; case UNW_PPC_R18: return _registers.__r18; case UNW_PPC_R19: return _registers.__r19; case UNW_PPC_R20: return _registers.__r20; case UNW_PPC_R21: return _registers.__r21; case UNW_PPC_R22: return _registers.__r22; case UNW_PPC_R23: return _registers.__r23; case UNW_PPC_R24: return _registers.__r24; case UNW_PPC_R25: return _registers.__r25; case UNW_PPC_R26: return _registers.__r26; case UNW_PPC_R27: return _registers.__r27; case UNW_PPC_R28: return _registers.__r28; case UNW_PPC_R29: return _registers.__r29; case UNW_PPC_R30: return _registers.__r30; case UNW_PPC_R31: return _registers.__r31; case UNW_PPC_LR: return _registers.__lr; case UNW_PPC_CR0: return (_registers.__cr & 0xF0000000); case UNW_PPC_CR1: return (_registers.__cr & 0x0F000000); case UNW_PPC_CR2: return (_registers.__cr & 0x00F00000); case UNW_PPC_CR3: return (_registers.__cr & 0x000F0000); case UNW_PPC_CR4: return (_registers.__cr & 0x0000F000); case UNW_PPC_CR5: return (_registers.__cr & 0x00000F00); case UNW_PPC_CR6: return (_registers.__cr & 0x000000F0); case UNW_PPC_CR7: return (_registers.__cr & 0x0000000F); case UNW_PPC_VRSAVE: return _registers.__vrsave; } _LIBUNWIND_ABORT("unsupported ppc register"); } inline void Registers_ppc::setRegister(int regNum, uint32_t value) { //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value); switch (regNum) { case UNW_REG_IP: _registers.__srr0 = value; return; case UNW_REG_SP: _registers.__r1 = value; return; case UNW_PPC_R0: _registers.__r0 = value; return; case UNW_PPC_R1: _registers.__r1 = value; return; case UNW_PPC_R2: _registers.__r2 = value; return; case UNW_PPC_R3: _registers.__r3 = value; return; case UNW_PPC_R4: _registers.__r4 = value; return; case UNW_PPC_R5: _registers.__r5 = value; return; case UNW_PPC_R6: _registers.__r6 = value; return; case UNW_PPC_R7: _registers.__r7 = value; return; case UNW_PPC_R8: _registers.__r8 = value; return; case UNW_PPC_R9: _registers.__r9 = value; return; case UNW_PPC_R10: _registers.__r10 = value; return; case UNW_PPC_R11: _registers.__r11 = value; return; case UNW_PPC_R12: _registers.__r12 = value; return; case UNW_PPC_R13: _registers.__r13 = value; return; case UNW_PPC_R14: _registers.__r14 = value; return; case UNW_PPC_R15: _registers.__r15 = value; return; case UNW_PPC_R16: _registers.__r16 = value; return; case UNW_PPC_R17: _registers.__r17 = value; return; case UNW_PPC_R18: _registers.__r18 = value; return; case UNW_PPC_R19: _registers.__r19 = value; return; case UNW_PPC_R20: _registers.__r20 = value; return; case UNW_PPC_R21: _registers.__r21 = value; return; case UNW_PPC_R22: _registers.__r22 = value; return; case UNW_PPC_R23: _registers.__r23 = value; return; case UNW_PPC_R24: _registers.__r24 = value; return; case UNW_PPC_R25: _registers.__r25 = value; return; case UNW_PPC_R26: _registers.__r26 = value; return; case UNW_PPC_R27: _registers.__r27 = value; return; case UNW_PPC_R28: _registers.__r28 = value; return; case UNW_PPC_R29: _registers.__r29 = value; return; case UNW_PPC_R30: _registers.__r30 = value; return; case UNW_PPC_R31: _registers.__r31 = value; return; case UNW_PPC_MQ: _registers.__mq = value; return; case UNW_PPC_LR: _registers.__lr = value; return; case UNW_PPC_CTR: _registers.__ctr = value; return; case UNW_PPC_CR0: _registers.__cr &= 0x0FFFFFFF; _registers.__cr |= (value & 0xF0000000); return; case UNW_PPC_CR1: _registers.__cr &= 0xF0FFFFFF; _registers.__cr |= (value & 0x0F000000); return; case UNW_PPC_CR2: _registers.__cr &= 0xFF0FFFFF; _registers.__cr |= (value & 0x00F00000); return; case UNW_PPC_CR3: _registers.__cr &= 0xFFF0FFFF; _registers.__cr |= (value & 0x000F0000); return; case UNW_PPC_CR4: _registers.__cr &= 0xFFFF0FFF; _registers.__cr |= (value & 0x0000F000); return; case UNW_PPC_CR5: _registers.__cr &= 0xFFFFF0FF; _registers.__cr |= (value & 0x00000F00); return; case UNW_PPC_CR6: _registers.__cr &= 0xFFFFFF0F; _registers.__cr |= (value & 0x000000F0); return; case UNW_PPC_CR7: _registers.__cr &= 0xFFFFFFF0; _registers.__cr |= (value & 0x0000000F); return; case UNW_PPC_VRSAVE: _registers.__vrsave = value; return; // not saved return; case UNW_PPC_XER: _registers.__xer = value; return; case UNW_PPC_AP: case UNW_PPC_VSCR: case UNW_PPC_SPEFSCR: // not saved return; } _LIBUNWIND_ABORT("unsupported ppc register"); } inline bool Registers_ppc::validFloatRegister(int regNum) const { if (regNum < UNW_PPC_F0) return false; if (regNum > UNW_PPC_F31) return false; return true; } inline double Registers_ppc::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; } inline void Registers_ppc::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; } inline bool Registers_ppc::validVectorRegister(int regNum) const { if (regNum < UNW_PPC_V0) return false; if (regNum > UNW_PPC_V31) return false; return true; } inline v128 Registers_ppc::getVectorRegister(int regNum) const { assert(validVectorRegister(regNum)); v128 result = _vectorRegisters[regNum - UNW_PPC_V0]; return result; } inline void Registers_ppc::setVectorRegister(int regNum, v128 value) { assert(validVectorRegister(regNum)); _vectorRegisters[regNum - UNW_PPC_V0] = value; } inline const char *Registers_ppc::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "ip"; case UNW_REG_SP: return "sp"; case UNW_PPC_R0: return "r0"; case UNW_PPC_R1: return "r1"; case UNW_PPC_R2: return "r2"; case UNW_PPC_R3: return "r3"; case UNW_PPC_R4: return "r4"; case UNW_PPC_R5: return "r5"; case UNW_PPC_R6: return "r6"; case UNW_PPC_R7: return "r7"; case UNW_PPC_R8: return "r8"; case UNW_PPC_R9: return "r9"; case UNW_PPC_R10: return "r10"; case UNW_PPC_R11: return "r11"; case UNW_PPC_R12: return "r12"; case UNW_PPC_R13: return "r13"; case UNW_PPC_R14: return "r14"; case UNW_PPC_R15: return "r15"; case UNW_PPC_R16: return "r16"; case UNW_PPC_R17: return "r17"; case UNW_PPC_R18: return "r18"; case UNW_PPC_R19: return "r19"; case UNW_PPC_R20: return "r20"; case UNW_PPC_R21: return "r21"; case UNW_PPC_R22: return "r22"; case UNW_PPC_R23: return "r23"; case UNW_PPC_R24: return "r24"; case UNW_PPC_R25: return "r25"; case UNW_PPC_R26: return "r26"; case UNW_PPC_R27: return "r27"; case UNW_PPC_R28: return "r28"; case UNW_PPC_R29: return "r29"; case UNW_PPC_R30: return "r30"; case UNW_PPC_R31: return "r31"; case UNW_PPC_F0: return "fp0"; case UNW_PPC_F1: return "fp1"; case UNW_PPC_F2: return "fp2"; case UNW_PPC_F3: return "fp3"; case UNW_PPC_F4: return "fp4"; case UNW_PPC_F5: return "fp5"; case UNW_PPC_F6: return "fp6"; case UNW_PPC_F7: return "fp7"; case UNW_PPC_F8: return "fp8"; case UNW_PPC_F9: return "fp9"; case UNW_PPC_F10: return "fp10"; case UNW_PPC_F11: return "fp11"; case UNW_PPC_F12: return "fp12"; case UNW_PPC_F13: return "fp13"; case UNW_PPC_F14: return "fp14"; case UNW_PPC_F15: return "fp15"; case UNW_PPC_F16: return "fp16"; case UNW_PPC_F17: return "fp17"; case UNW_PPC_F18: return "fp18"; case UNW_PPC_F19: return "fp19"; case UNW_PPC_F20: return "fp20"; case UNW_PPC_F21: return "fp21"; case UNW_PPC_F22: return "fp22"; case UNW_PPC_F23: return "fp23"; case UNW_PPC_F24: return "fp24"; case UNW_PPC_F25: return "fp25"; case UNW_PPC_F26: return "fp26"; case UNW_PPC_F27: return "fp27"; case UNW_PPC_F28: return "fp28"; case UNW_PPC_F29: return "fp29"; case UNW_PPC_F30: return "fp30"; case UNW_PPC_F31: return "fp31"; case UNW_PPC_LR: return "lr"; default: return "unknown register"; } } #endif // _LIBUNWIND_TARGET_PPC #if defined(_LIBUNWIND_TARGET_PPC64) /// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC /// process. class _LIBUNWIND_HIDDEN Registers_ppc64 { public: Registers_ppc64(); Registers_ppc64(const void *registers); bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } static int getArch() { return REGISTERS_PPC64; } uint64_t getSP() const { return _registers.__r1; } void setSP(uint64_t value) { _registers.__r1 = value; } uint64_t getIP() const { return _registers.__srr0; } void setIP(uint64_t value) { _registers.__srr0 = value; } private: struct ppc64_thread_state_t { uint64_t __srr0; // Instruction address register (PC) uint64_t __srr1; // Machine state register (supervisor) uint64_t __r0; uint64_t __r1; uint64_t __r2; uint64_t __r3; uint64_t __r4; uint64_t __r5; uint64_t __r6; uint64_t __r7; uint64_t __r8; uint64_t __r9; uint64_t __r10; uint64_t __r11; uint64_t __r12; uint64_t __r13; uint64_t __r14; uint64_t __r15; uint64_t __r16; uint64_t __r17; uint64_t __r18; uint64_t __r19; uint64_t __r20; uint64_t __r21; uint64_t __r22; uint64_t __r23; uint64_t __r24; uint64_t __r25; uint64_t __r26; uint64_t __r27; uint64_t __r28; uint64_t __r29; uint64_t __r30; uint64_t __r31; uint64_t __cr; // Condition register uint64_t __xer; // User's integer exception register uint64_t __lr; // Link register uint64_t __ctr; // Count register uint64_t __vrsave; // Vector Save Register }; union ppc64_vsr_t { struct asfloat_s { double f; uint64_t v2; } asfloat; v128 v; }; ppc64_thread_state_t _registers; ppc64_vsr_t _vectorScalarRegisters[64]; static int getVectorRegNum(int num); }; inline Registers_ppc64::Registers_ppc64(const void *registers) { static_assert((check_fit::does_fit), "ppc64 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); static_assert(sizeof(_registers) == 312, "expected vector scalar register offset to be 312"); memcpy(&_vectorScalarRegisters, static_cast(registers) + sizeof(_registers), sizeof(_vectorScalarRegisters)); static_assert(sizeof(_registers) + sizeof(_vectorScalarRegisters) == 1336, "expected vector register offset to be 1336 bytes"); } inline Registers_ppc64::Registers_ppc64() { memset(&_registers, 0, sizeof(_registers)); memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters)); } inline bool Registers_ppc64::validRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: case UNW_REG_SP: case UNW_PPC64_XER: case UNW_PPC64_LR: case UNW_PPC64_CTR: case UNW_PPC64_VRSAVE: return true; } if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31) return true; if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7) return true; return false; } inline uint64_t Registers_ppc64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: return _registers.__srr0; case UNW_PPC64_R0: return _registers.__r0; case UNW_PPC64_R1: case UNW_REG_SP: return _registers.__r1; case UNW_PPC64_R2: return _registers.__r2; case UNW_PPC64_R3: return _registers.__r3; case UNW_PPC64_R4: return _registers.__r4; case UNW_PPC64_R5: return _registers.__r5; case UNW_PPC64_R6: return _registers.__r6; case UNW_PPC64_R7: return _registers.__r7; case UNW_PPC64_R8: return _registers.__r8; case UNW_PPC64_R9: return _registers.__r9; case UNW_PPC64_R10: return _registers.__r10; case UNW_PPC64_R11: return _registers.__r11; case UNW_PPC64_R12: return _registers.__r12; case UNW_PPC64_R13: return _registers.__r13; case UNW_PPC64_R14: return _registers.__r14; case UNW_PPC64_R15: return _registers.__r15; case UNW_PPC64_R16: return _registers.__r16; case UNW_PPC64_R17: return _registers.__r17; case UNW_PPC64_R18: return _registers.__r18; case UNW_PPC64_R19: return _registers.__r19; case UNW_PPC64_R20: return _registers.__r20; case UNW_PPC64_R21: return _registers.__r21; case UNW_PPC64_R22: return _registers.__r22; case UNW_PPC64_R23: return _registers.__r23; case UNW_PPC64_R24: return _registers.__r24; case UNW_PPC64_R25: return _registers.__r25; case UNW_PPC64_R26: return _registers.__r26; case UNW_PPC64_R27: return _registers.__r27; case UNW_PPC64_R28: return _registers.__r28; case UNW_PPC64_R29: return _registers.__r29; case UNW_PPC64_R30: return _registers.__r30; case UNW_PPC64_R31: return _registers.__r31; case UNW_PPC64_CR0: return (_registers.__cr & 0xF0000000); case UNW_PPC64_CR1: return (_registers.__cr & 0x0F000000); case UNW_PPC64_CR2: return (_registers.__cr & 0x00F00000); case UNW_PPC64_CR3: return (_registers.__cr & 0x000F0000); case UNW_PPC64_CR4: return (_registers.__cr & 0x0000F000); case UNW_PPC64_CR5: return (_registers.__cr & 0x00000F00); case UNW_PPC64_CR6: return (_registers.__cr & 0x000000F0); case UNW_PPC64_CR7: return (_registers.__cr & 0x0000000F); case UNW_PPC64_XER: return _registers.__xer; case UNW_PPC64_LR: return _registers.__lr; case UNW_PPC64_CTR: return _registers.__ctr; case UNW_PPC64_VRSAVE: return _registers.__vrsave; } _LIBUNWIND_ABORT("unsupported ppc64 register"); } inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: _registers.__srr0 = value; return; case UNW_PPC64_R0: _registers.__r0 = value; return; case UNW_PPC64_R1: case UNW_REG_SP: _registers.__r1 = value; return; case UNW_PPC64_R2: _registers.__r2 = value; return; case UNW_PPC64_R3: _registers.__r3 = value; return; case UNW_PPC64_R4: _registers.__r4 = value; return; case UNW_PPC64_R5: _registers.__r5 = value; return; case UNW_PPC64_R6: _registers.__r6 = value; return; case UNW_PPC64_R7: _registers.__r7 = value; return; case UNW_PPC64_R8: _registers.__r8 = value; return; case UNW_PPC64_R9: _registers.__r9 = value; return; case UNW_PPC64_R10: _registers.__r10 = value; return; case UNW_PPC64_R11: _registers.__r11 = value; return; case UNW_PPC64_R12: _registers.__r12 = value; return; case UNW_PPC64_R13: _registers.__r13 = value; return; case UNW_PPC64_R14: _registers.__r14 = value; return; case UNW_PPC64_R15: _registers.__r15 = value; return; case UNW_PPC64_R16: _registers.__r16 = value; return; case UNW_PPC64_R17: _registers.__r17 = value; return; case UNW_PPC64_R18: _registers.__r18 = value; return; case UNW_PPC64_R19: _registers.__r19 = value; return; case UNW_PPC64_R20: _registers.__r20 = value; return; case UNW_PPC64_R21: _registers.__r21 = value; return; case UNW_PPC64_R22: _registers.__r22 = value; return; case UNW_PPC64_R23: _registers.__r23 = value; return; case UNW_PPC64_R24: _registers.__r24 = value; return; case UNW_PPC64_R25: _registers.__r25 = value; return; case UNW_PPC64_R26: _registers.__r26 = value; return; case UNW_PPC64_R27: _registers.__r27 = value; return; case UNW_PPC64_R28: _registers.__r28 = value; return; case UNW_PPC64_R29: _registers.__r29 = value; return; case UNW_PPC64_R30: _registers.__r30 = value; return; case UNW_PPC64_R31: _registers.__r31 = value; return; case UNW_PPC64_CR0: _registers.__cr &= 0x0FFFFFFF; _registers.__cr |= (value & 0xF0000000); return; case UNW_PPC64_CR1: _registers.__cr &= 0xF0FFFFFF; _registers.__cr |= (value & 0x0F000000); return; case UNW_PPC64_CR2: _registers.__cr &= 0xFF0FFFFF; _registers.__cr |= (value & 0x00F00000); return; case UNW_PPC64_CR3: _registers.__cr &= 0xFFF0FFFF; _registers.__cr |= (value & 0x000F0000); return; case UNW_PPC64_CR4: _registers.__cr &= 0xFFFF0FFF; _registers.__cr |= (value & 0x0000F000); return; case UNW_PPC64_CR5: _registers.__cr &= 0xFFFFF0FF; _registers.__cr |= (value & 0x00000F00); return; case UNW_PPC64_CR6: _registers.__cr &= 0xFFFFFF0F; _registers.__cr |= (value & 0x000000F0); return; case UNW_PPC64_CR7: _registers.__cr &= 0xFFFFFFF0; _registers.__cr |= (value & 0x0000000F); return; case UNW_PPC64_XER: _registers.__xer = value; return; case UNW_PPC64_LR: _registers.__lr = value; return; case UNW_PPC64_CTR: _registers.__ctr = value; return; case UNW_PPC64_VRSAVE: _registers.__vrsave = value; return; } _LIBUNWIND_ABORT("unsupported ppc64 register"); } inline bool Registers_ppc64::validFloatRegister(int regNum) const { return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; } inline double Registers_ppc64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; } inline void Registers_ppc64::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; } inline bool Registers_ppc64::validVectorRegister(int regNum) const { #ifdef PPC64_HAS_VMX if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) return true; if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) return true; #else if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) return true; #endif return false; } inline int Registers_ppc64::getVectorRegNum(int num) { if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31) return num - UNW_PPC64_VS0; else return num - UNW_PPC64_VS32 + 32; } inline v128 Registers_ppc64::getVectorRegister(int regNum) const { assert(validVectorRegister(regNum)); return _vectorScalarRegisters[getVectorRegNum(regNum)].v; } inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) { assert(validVectorRegister(regNum)); _vectorScalarRegisters[getVectorRegNum(regNum)].v = value; } inline const char *Registers_ppc64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "ip"; case UNW_REG_SP: return "sp"; case UNW_PPC64_R0: return "r0"; case UNW_PPC64_R1: return "r1"; case UNW_PPC64_R2: return "r2"; case UNW_PPC64_R3: return "r3"; case UNW_PPC64_R4: return "r4"; case UNW_PPC64_R5: return "r5"; case UNW_PPC64_R6: return "r6"; case UNW_PPC64_R7: return "r7"; case UNW_PPC64_R8: return "r8"; case UNW_PPC64_R9: return "r9"; case UNW_PPC64_R10: return "r10"; case UNW_PPC64_R11: return "r11"; case UNW_PPC64_R12: return "r12"; case UNW_PPC64_R13: return "r13"; case UNW_PPC64_R14: return "r14"; case UNW_PPC64_R15: return "r15"; case UNW_PPC64_R16: return "r16"; case UNW_PPC64_R17: return "r17"; case UNW_PPC64_R18: return "r18"; case UNW_PPC64_R19: return "r19"; case UNW_PPC64_R20: return "r20"; case UNW_PPC64_R21: return "r21"; case UNW_PPC64_R22: return "r22"; case UNW_PPC64_R23: return "r23"; case UNW_PPC64_R24: return "r24"; case UNW_PPC64_R25: return "r25"; case UNW_PPC64_R26: return "r26"; case UNW_PPC64_R27: return "r27"; case UNW_PPC64_R28: return "r28"; case UNW_PPC64_R29: return "r29"; case UNW_PPC64_R30: return "r30"; case UNW_PPC64_R31: return "r31"; case UNW_PPC64_CR0: return "cr0"; case UNW_PPC64_CR1: return "cr1"; case UNW_PPC64_CR2: return "cr2"; case UNW_PPC64_CR3: return "cr3"; case UNW_PPC64_CR4: return "cr4"; case UNW_PPC64_CR5: return "cr5"; case UNW_PPC64_CR6: return "cr6"; case UNW_PPC64_CR7: return "cr7"; case UNW_PPC64_XER: return "xer"; case UNW_PPC64_LR: return "lr"; case UNW_PPC64_CTR: return "ctr"; case UNW_PPC64_VRSAVE: return "vrsave"; case UNW_PPC64_F0: return "fp0"; case UNW_PPC64_F1: return "fp1"; case UNW_PPC64_F2: return "fp2"; case UNW_PPC64_F3: return "fp3"; case UNW_PPC64_F4: return "fp4"; case UNW_PPC64_F5: return "fp5"; case UNW_PPC64_F6: return "fp6"; case UNW_PPC64_F7: return "fp7"; case UNW_PPC64_F8: return "fp8"; case UNW_PPC64_F9: return "fp9"; case UNW_PPC64_F10: return "fp10"; case UNW_PPC64_F11: return "fp11"; case UNW_PPC64_F12: return "fp12"; case UNW_PPC64_F13: return "fp13"; case UNW_PPC64_F14: return "fp14"; case UNW_PPC64_F15: return "fp15"; case UNW_PPC64_F16: return "fp16"; case UNW_PPC64_F17: return "fp17"; case UNW_PPC64_F18: return "fp18"; case UNW_PPC64_F19: return "fp19"; case UNW_PPC64_F20: return "fp20"; case UNW_PPC64_F21: return "fp21"; case UNW_PPC64_F22: return "fp22"; case UNW_PPC64_F23: return "fp23"; case UNW_PPC64_F24: return "fp24"; case UNW_PPC64_F25: return "fp25"; case UNW_PPC64_F26: return "fp26"; case UNW_PPC64_F27: return "fp27"; case UNW_PPC64_F28: return "fp28"; case UNW_PPC64_F29: return "fp29"; case UNW_PPC64_F30: return "fp30"; case UNW_PPC64_F31: return "fp31"; case UNW_PPC64_V0: return "v0"; case UNW_PPC64_V1: return "v1"; case UNW_PPC64_V2: return "v2"; case UNW_PPC64_V3: return "v3"; case UNW_PPC64_V4: return "v4"; case UNW_PPC64_V5: return "v5"; case UNW_PPC64_V6: return "v6"; case UNW_PPC64_V7: return "v7"; case UNW_PPC64_V8: return "v8"; case UNW_PPC64_V9: return "v9"; case UNW_PPC64_V10: return "v10"; case UNW_PPC64_V11: return "v11"; case UNW_PPC64_V12: return "v12"; case UNW_PPC64_V13: return "v13"; case UNW_PPC64_V14: return "v14"; case UNW_PPC64_V15: return "v15"; case UNW_PPC64_V16: return "v16"; case UNW_PPC64_V17: return "v17"; case UNW_PPC64_V18: return "v18"; case UNW_PPC64_V19: return "v19"; case UNW_PPC64_V20: return "v20"; case UNW_PPC64_V21: return "v21"; case UNW_PPC64_V22: return "v22"; case UNW_PPC64_V23: return "v23"; case UNW_PPC64_V24: return "v24"; case UNW_PPC64_V25: return "v25"; case UNW_PPC64_V26: return "v26"; case UNW_PPC64_V27: return "v27"; case UNW_PPC64_V28: return "v28"; case UNW_PPC64_V29: return "v29"; case UNW_PPC64_V30: return "v30"; case UNW_PPC64_V31: return "v31"; } return "unknown register"; } #endif // _LIBUNWIND_TARGET_PPC64 #if defined(_LIBUNWIND_TARGET_AARCH64) /// Registers_arm64 holds the register state of a thread in a 64-bit arm /// process. class _LIBUNWIND_HIDDEN Registers_arm64 { public: Registers_arm64(); Registers_arm64(const void *registers); bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } static int getArch() { return REGISTERS_ARM64; } uint64_t getSP() const { return _registers.__sp; } void setSP(uint64_t value) { _registers.__sp = value; } uint64_t getIP() const { return _registers.__pc; } void setIP(uint64_t value) { _registers.__pc = value; } uint64_t getFP() const { return _registers.__fp; } void setFP(uint64_t value) { _registers.__fp = value; } private: 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 }; GPRs _registers; double _vectorHalfRegisters[32]; // 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. }; 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, "expected VFP registers to be at offset 272"); memcpy(_vectorHalfRegisters, static_cast(registers) + sizeof(GPRs), sizeof(_vectorHalfRegisters)); } inline Registers_arm64::Registers_arm64() { memset(&_registers, 0, sizeof(_registers)); memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); } inline bool Registers_arm64::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum > 95) return false; if (regNum == UNW_ARM64_RA_SIGN_STATE) return true; if ((regNum > 31) && (regNum < 64)) return false; return true; } inline uint64_t Registers_arm64::getRegister(int regNum) const { if (regNum == UNW_REG_IP) return _registers.__pc; if (regNum == UNW_REG_SP) return _registers.__sp; if (regNum == UNW_ARM64_RA_SIGN_STATE) return _registers.__ra_sign_state; if ((regNum >= 0) && (regNum < 32)) return _registers.__x[regNum]; _LIBUNWIND_ABORT("unsupported arm64 register"); } inline void Registers_arm64::setRegister(int regNum, uint64_t value) { if (regNum == UNW_REG_IP) _registers.__pc = value; else if (regNum == UNW_REG_SP) _registers.__sp = value; else if (regNum == UNW_ARM64_RA_SIGN_STATE) _registers.__ra_sign_state = value; else if ((regNum >= 0) && (regNum < 32)) _registers.__x[regNum] = value; else _LIBUNWIND_ABORT("unsupported arm64 register"); } inline const char *Registers_arm64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "pc"; case UNW_REG_SP: return "sp"; case UNW_ARM64_X0: return "x0"; case UNW_ARM64_X1: return "x1"; case UNW_ARM64_X2: return "x2"; case UNW_ARM64_X3: return "x3"; case UNW_ARM64_X4: return "x4"; case UNW_ARM64_X5: return "x5"; case UNW_ARM64_X6: return "x6"; case UNW_ARM64_X7: return "x7"; case UNW_ARM64_X8: return "x8"; case UNW_ARM64_X9: return "x9"; case UNW_ARM64_X10: return "x10"; case UNW_ARM64_X11: return "x11"; case UNW_ARM64_X12: return "x12"; case UNW_ARM64_X13: return "x13"; case UNW_ARM64_X14: return "x14"; case UNW_ARM64_X15: return "x15"; case UNW_ARM64_X16: return "x16"; case UNW_ARM64_X17: return "x17"; case UNW_ARM64_X18: return "x18"; case UNW_ARM64_X19: return "x19"; case UNW_ARM64_X20: return "x20"; case UNW_ARM64_X21: return "x21"; case UNW_ARM64_X22: return "x22"; case UNW_ARM64_X23: return "x23"; case UNW_ARM64_X24: return "x24"; case UNW_ARM64_X25: return "x25"; case UNW_ARM64_X26: return "x26"; case UNW_ARM64_X27: return "x27"; case UNW_ARM64_X28: return "x28"; case UNW_ARM64_X29: return "fp"; case UNW_ARM64_X30: return "lr"; case UNW_ARM64_X31: return "sp"; case UNW_ARM64_D0: return "d0"; case UNW_ARM64_D1: return "d1"; case UNW_ARM64_D2: return "d2"; case UNW_ARM64_D3: return "d3"; case UNW_ARM64_D4: return "d4"; case UNW_ARM64_D5: return "d5"; case UNW_ARM64_D6: return "d6"; case UNW_ARM64_D7: return "d7"; case UNW_ARM64_D8: return "d8"; case UNW_ARM64_D9: return "d9"; case UNW_ARM64_D10: return "d10"; case UNW_ARM64_D11: return "d11"; case UNW_ARM64_D12: return "d12"; case UNW_ARM64_D13: return "d13"; case UNW_ARM64_D14: return "d14"; case UNW_ARM64_D15: return "d15"; case UNW_ARM64_D16: return "d16"; case UNW_ARM64_D17: return "d17"; case UNW_ARM64_D18: return "d18"; case UNW_ARM64_D19: return "d19"; case UNW_ARM64_D20: return "d20"; case UNW_ARM64_D21: return "d21"; case UNW_ARM64_D22: return "d22"; case UNW_ARM64_D23: return "d23"; case UNW_ARM64_D24: return "d24"; case UNW_ARM64_D25: return "d25"; case UNW_ARM64_D26: return "d26"; case UNW_ARM64_D27: return "d27"; case UNW_ARM64_D28: return "d28"; case UNW_ARM64_D29: return "d29"; case UNW_ARM64_D30: return "d30"; case UNW_ARM64_D31: return "d31"; default: return "unknown register"; } } inline bool Registers_arm64::validFloatRegister(int regNum) const { if (regNum < UNW_ARM64_D0) return false; if (regNum > UNW_ARM64_D31) return false; return true; } inline double Registers_arm64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; } inline void Registers_arm64::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; } inline bool Registers_arm64::validVectorRegister(int) const { return false; } inline v128 Registers_arm64::getVectorRegister(int) const { _LIBUNWIND_ABORT("no arm64 vector register support yet"); } inline void Registers_arm64::setVectorRegister(int, v128) { _LIBUNWIND_ABORT("no arm64 vector register support yet"); } #endif // _LIBUNWIND_TARGET_AARCH64 #if defined(_LIBUNWIND_TARGET_ARM) /// Registers_arm holds the register state of a thread in a 32-bit arm /// process. /// /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit, /// this uses more memory than required. class _LIBUNWIND_HIDDEN Registers_arm { public: Registers_arm(); Registers_arm(const void *registers); bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; unw_fpreg_t getFloatRegister(int num); void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto() { restoreSavedFloatRegisters(); restoreCoreAndJumpTo(); } static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } static int getArch() { return REGISTERS_ARM; } uint32_t getSP() const { return _registers.__sp; } void setSP(uint32_t value) { _registers.__sp = value; } uint32_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } void saveVFPAsX() { assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); _use_X_for_vfp_save = true; } void restoreSavedFloatRegisters() { if (_saved_vfp_d0_d15) { if (_use_X_for_vfp_save) restoreVFPWithFLDMX(_vfp_d0_d15_pad); else restoreVFPWithFLDMD(_vfp_d0_d15_pad); } if (_saved_vfp_d16_d31) restoreVFPv3(_vfp_d16_d31); #if defined(__ARM_WMMX) if (_saved_iwmmx) restoreiWMMX(_iwmmx); if (_saved_iwmmx_control) restoreiWMMXControl(_iwmmx_control); #endif } private: struct GPRs { 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 saveVFPWithFSTMD(void*); static void saveVFPWithFSTMX(void*); static void saveVFPv3(void*); static void restoreVFPWithFLDMD(void*); static void restoreVFPWithFLDMX(void*); static void restoreVFPv3(void*); #if defined(__ARM_WMMX) static void saveiWMMX(void*); static void saveiWMMXControl(uint32_t*); static void restoreiWMMX(void*); static void restoreiWMMXControl(uint32_t*); #endif void restoreCoreAndJumpTo(); // ARM registers GPRs _registers; // We save floating point registers lazily because we can't know ahead of // time which ones are used. See EHABI #4.7. // Whether D0-D15 are saved in the FTSMX instead of FSTMD format. // // See EHABI #7.5 that explains how matching instruction sequences for load // and store need to be used to correctly restore the exact register bits. bool _use_X_for_vfp_save; // Whether VFP D0-D15 are saved. bool _saved_vfp_d0_d15; // Whether VFPv3 D16-D31 are saved. bool _saved_vfp_d16_d31; // VFP registers D0-D15, + padding if saved using FSTMX unw_fpreg_t _vfp_d0_d15_pad[17]; // VFPv3 registers D16-D31, always saved using FSTMD unw_fpreg_t _vfp_d16_d31[16]; #if defined(__ARM_WMMX) // Whether iWMMX data registers are saved. bool _saved_iwmmx; // Whether iWMMX control registers are saved. mutable bool _saved_iwmmx_control; // iWMMX registers unw_fpreg_t _iwmmx[16]; // iWMMX control registers mutable uint32_t _iwmmx_control[4]; #endif }; inline Registers_arm::Registers_arm(const void *registers) : _use_X_for_vfp_save(false), _saved_vfp_d0_d15(false), _saved_vfp_d16_d31(false) { static_assert((check_fit::does_fit), "arm registers do not fit into unw_context_t"); // See __unw_getcontext() note about data. memcpy(&_registers, registers, sizeof(_registers)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) _saved_iwmmx = false; _saved_iwmmx_control = false; memset(&_iwmmx, 0, sizeof(_iwmmx)); memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); #endif } inline Registers_arm::Registers_arm() : _use_X_for_vfp_save(false), _saved_vfp_d0_d15(false), _saved_vfp_d16_d31(false) { memset(&_registers, 0, sizeof(_registers)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) _saved_iwmmx = false; _saved_iwmmx_control = false; memset(&_iwmmx, 0, sizeof(_iwmmx)); memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); #endif } inline bool Registers_arm::validRegister(int regNum) const { // Returns true for all non-VFP registers supported by the EHABI // virtual register set (VRS). if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; #if defined(__ARM_WMMX) if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) return true; #endif return false; } inline uint32_t Registers_arm::getRegister(int regNum) const { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) return _registers.__sp; if (regNum == UNW_ARM_LR) return _registers.__lr; if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) return _registers.__pc; if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) return _registers.__r[regNum]; #if defined(__ARM_WMMX) if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { if (!_saved_iwmmx_control) { _saved_iwmmx_control = true; saveiWMMXControl(_iwmmx_control); } return _iwmmx_control[regNum - UNW_ARM_WC0]; } #endif _LIBUNWIND_ABORT("unsupported arm register"); } inline void Registers_arm::setRegister(int regNum, uint32_t value) { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { _registers.__sp = value; return; } if (regNum == UNW_ARM_LR) { _registers.__lr = value; return; } if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { _registers.__pc = value; return; } if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { _registers.__r[regNum] = value; return; } #if defined(__ARM_WMMX) if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { if (!_saved_iwmmx_control) { _saved_iwmmx_control = true; saveiWMMXControl(_iwmmx_control); } _iwmmx_control[regNum - UNW_ARM_WC0] = value; return; } #endif _LIBUNWIND_ABORT("unsupported arm register"); } inline const char *Registers_arm::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: case UNW_ARM_IP: // UNW_ARM_R15 is alias return "pc"; case UNW_ARM_LR: // UNW_ARM_R14 is alias return "lr"; case UNW_REG_SP: case UNW_ARM_SP: // UNW_ARM_R13 is alias return "sp"; case UNW_ARM_R0: return "r0"; case UNW_ARM_R1: return "r1"; case UNW_ARM_R2: return "r2"; case UNW_ARM_R3: return "r3"; case UNW_ARM_R4: return "r4"; case UNW_ARM_R5: return "r5"; case UNW_ARM_R6: return "r6"; case UNW_ARM_R7: return "r7"; case UNW_ARM_R8: return "r8"; case UNW_ARM_R9: return "r9"; case UNW_ARM_R10: return "r10"; case UNW_ARM_R11: return "r11"; case UNW_ARM_R12: return "r12"; case UNW_ARM_S0: return "s0"; case UNW_ARM_S1: return "s1"; case UNW_ARM_S2: return "s2"; case UNW_ARM_S3: return "s3"; case UNW_ARM_S4: return "s4"; case UNW_ARM_S5: return "s5"; case UNW_ARM_S6: return "s6"; case UNW_ARM_S7: return "s7"; case UNW_ARM_S8: return "s8"; case UNW_ARM_S9: return "s9"; case UNW_ARM_S10: return "s10"; case UNW_ARM_S11: return "s11"; case UNW_ARM_S12: return "s12"; case UNW_ARM_S13: return "s13"; case UNW_ARM_S14: return "s14"; case UNW_ARM_S15: return "s15"; case UNW_ARM_S16: return "s16"; case UNW_ARM_S17: return "s17"; case UNW_ARM_S18: return "s18"; case UNW_ARM_S19: return "s19"; case UNW_ARM_S20: return "s20"; case UNW_ARM_S21: return "s21"; case UNW_ARM_S22: return "s22"; case UNW_ARM_S23: return "s23"; case UNW_ARM_S24: return "s24"; case UNW_ARM_S25: return "s25"; case UNW_ARM_S26: return "s26"; case UNW_ARM_S27: return "s27"; case UNW_ARM_S28: return "s28"; case UNW_ARM_S29: return "s29"; case UNW_ARM_S30: return "s30"; case UNW_ARM_S31: return "s31"; case UNW_ARM_D0: return "d0"; case UNW_ARM_D1: return "d1"; case UNW_ARM_D2: return "d2"; case UNW_ARM_D3: return "d3"; case UNW_ARM_D4: return "d4"; case UNW_ARM_D5: return "d5"; case UNW_ARM_D6: return "d6"; case UNW_ARM_D7: return "d7"; case UNW_ARM_D8: return "d8"; case UNW_ARM_D9: return "d9"; case UNW_ARM_D10: return "d10"; case UNW_ARM_D11: return "d11"; case UNW_ARM_D12: return "d12"; case UNW_ARM_D13: return "d13"; case UNW_ARM_D14: return "d14"; case UNW_ARM_D15: return "d15"; case UNW_ARM_D16: return "d16"; case UNW_ARM_D17: return "d17"; case UNW_ARM_D18: return "d18"; case UNW_ARM_D19: return "d19"; case UNW_ARM_D20: return "d20"; case UNW_ARM_D21: return "d21"; case UNW_ARM_D22: return "d22"; case UNW_ARM_D23: return "d23"; case UNW_ARM_D24: return "d24"; case UNW_ARM_D25: return "d25"; case UNW_ARM_D26: return "d26"; case UNW_ARM_D27: return "d27"; case UNW_ARM_D28: return "d28"; case UNW_ARM_D29: return "d29"; case UNW_ARM_D30: return "d30"; case UNW_ARM_D31: return "d31"; default: return "unknown register"; } } inline bool Registers_arm::validFloatRegister(int regNum) const { // NOTE: Consider the intel MMX registers floating points so the // __unw_get_fpreg can be used to transmit the 64-bit data back. return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31)) #if defined(__ARM_WMMX) || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15)) #endif ; } inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) { if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { if (!_saved_vfp_d0_d15) { _saved_vfp_d0_d15 = true; if (_use_X_for_vfp_save) saveVFPWithFSTMX(_vfp_d0_d15_pad); else saveVFPWithFSTMD(_vfp_d0_d15_pad); } return _vfp_d0_d15_pad[regNum - UNW_ARM_D0]; } if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { if (!_saved_vfp_d16_d31) { _saved_vfp_d16_d31 = true; saveVFPv3(_vfp_d16_d31); } return _vfp_d16_d31[regNum - UNW_ARM_D16]; } #if defined(__ARM_WMMX) if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { if (!_saved_iwmmx) { _saved_iwmmx = true; saveiWMMX(_iwmmx); } return _iwmmx[regNum - UNW_ARM_WR0]; } #endif _LIBUNWIND_ABORT("Unknown ARM float register"); } inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) { if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { if (!_saved_vfp_d0_d15) { _saved_vfp_d0_d15 = true; if (_use_X_for_vfp_save) saveVFPWithFSTMX(_vfp_d0_d15_pad); else saveVFPWithFSTMD(_vfp_d0_d15_pad); } _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value; return; } if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { if (!_saved_vfp_d16_d31) { _saved_vfp_d16_d31 = true; saveVFPv3(_vfp_d16_d31); } _vfp_d16_d31[regNum - UNW_ARM_D16] = value; return; } #if defined(__ARM_WMMX) if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { if (!_saved_iwmmx) { _saved_iwmmx = true; saveiWMMX(_iwmmx); } _iwmmx[regNum - UNW_ARM_WR0] = value; return; } #endif _LIBUNWIND_ABORT("Unknown ARM float register"); } inline bool Registers_arm::validVectorRegister(int) const { return false; } inline v128 Registers_arm::getVectorRegister(int) const { _LIBUNWIND_ABORT("ARM vector support not implemented"); } inline void Registers_arm::setVectorRegister(int, v128) { _LIBUNWIND_ABORT("ARM vector support not implemented"); } #endif // _LIBUNWIND_TARGET_ARM #if defined(_LIBUNWIND_TARGET_OR1K) /// Registers_or1k holds the register state of a thread in an OpenRISC1000 /// process. class _LIBUNWIND_HIDDEN Registers_or1k { public: Registers_or1k(); Registers_or1k(const void *registers); bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } static int getArch() { return REGISTERS_OR1K; } uint64_t getSP() const { return _registers.__r[1]; } void setSP(uint32_t value) { _registers.__r[1] = value; } uint64_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } private: struct or1k_thread_state_t { unsigned int __r[32]; // r0-r31 unsigned int __pc; // Program counter unsigned int __epcr; // Program counter at exception }; or1k_thread_state_t _registers; }; inline Registers_or1k::Registers_or1k(const void *registers) { static_assert((check_fit::does_fit), "or1k registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } inline Registers_or1k::Registers_or1k() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_or1k::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum <= UNW_OR1K_R31) return true; if (regNum == UNW_OR1K_EPCR) return true; return false; } inline uint32_t Registers_or1k::getRegister(int regNum) const { if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) return _registers.__r[regNum - UNW_OR1K_R0]; switch (regNum) { case UNW_REG_IP: return _registers.__pc; case UNW_REG_SP: return _registers.__r[1]; case UNW_OR1K_EPCR: return _registers.__epcr; } _LIBUNWIND_ABORT("unsupported or1k register"); } inline void Registers_or1k::setRegister(int regNum, uint32_t value) { if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) { _registers.__r[regNum - UNW_OR1K_R0] = value; return; } switch (regNum) { case UNW_REG_IP: _registers.__pc = value; return; case UNW_REG_SP: _registers.__r[1] = value; return; case UNW_OR1K_EPCR: _registers.__epcr = value; return; } _LIBUNWIND_ABORT("unsupported or1k register"); } inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { return false; } inline double Registers_or1k::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("or1k float support not implemented"); } inline void Registers_or1k::setFloatRegister(int /* regNum */, double /* value */) { _LIBUNWIND_ABORT("or1k float support not implemented"); } inline bool Registers_or1k::validVectorRegister(int /* regNum */) const { return false; } inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const { _LIBUNWIND_ABORT("or1k vector support not implemented"); } inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) { _LIBUNWIND_ABORT("or1k vector support not implemented"); } inline const char *Registers_or1k::getRegisterName(int regNum) { switch (regNum) { case UNW_OR1K_R0: return "r0"; case UNW_OR1K_R1: return "r1"; case UNW_OR1K_R2: return "r2"; case UNW_OR1K_R3: return "r3"; case UNW_OR1K_R4: return "r4"; case UNW_OR1K_R5: return "r5"; case UNW_OR1K_R6: return "r6"; case UNW_OR1K_R7: return "r7"; case UNW_OR1K_R8: return "r8"; case UNW_OR1K_R9: return "r9"; case UNW_OR1K_R10: return "r10"; case UNW_OR1K_R11: return "r11"; case UNW_OR1K_R12: return "r12"; case UNW_OR1K_R13: return "r13"; case UNW_OR1K_R14: return "r14"; case UNW_OR1K_R15: return "r15"; case UNW_OR1K_R16: return "r16"; case UNW_OR1K_R17: return "r17"; case UNW_OR1K_R18: return "r18"; case UNW_OR1K_R19: return "r19"; case UNW_OR1K_R20: return "r20"; case UNW_OR1K_R21: return "r21"; case UNW_OR1K_R22: return "r22"; case UNW_OR1K_R23: return "r23"; case UNW_OR1K_R24: return "r24"; case UNW_OR1K_R25: return "r25"; case UNW_OR1K_R26: return "r26"; case UNW_OR1K_R27: return "r27"; case UNW_OR1K_R28: return "r28"; case UNW_OR1K_R29: return "r29"; case UNW_OR1K_R30: return "r30"; case UNW_OR1K_R31: return "r31"; case UNW_OR1K_EPCR: return "EPCR"; default: return "unknown register"; } } #endif // _LIBUNWIND_TARGET_OR1K - -#if defined(_LIBUNWIND_TARGET_RISCV) -/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V -/// process. -class _LIBUNWIND_HIDDEN Registers_riscv { -public: - Registers_riscv(); - Registers_riscv(const void *registers); - - bool validRegister(int num) const; - uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); - bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); - bool validVectorRegister(int num) const; - v128 getVectorRegister(int num) const; - void setVectorRegister(int num, v128 value); - static const char *getRegisterName(int num); - void jumpto(); - static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } - static int getArch() { return REGISTERS_RISCV; } - - uint64_t getSP() const { return _registers.__x[2]; } - void setSP(uint64_t value) { _registers.__x[2] = value; } - uint64_t getIP() const { return _registers.__x[1]; } - void setIP(uint64_t value) { _registers.__x[1] = value; } - -private: - struct GPRs { - uint64_t __x[32]; // x0-x31 - }; - - GPRs _registers; - double _vectorHalfRegisters[32]; - // 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. -}; - -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)); - static_assert(sizeof(GPRs) == 0x100, - "expected VFP registers to be at offset 256"); - memcpy(_vectorHalfRegisters, - static_cast(registers) + sizeof(GPRs), - sizeof(_vectorHalfRegisters)); -} - -inline Registers_riscv::Registers_riscv() { - memset(&_registers, 0, sizeof(_registers)); - memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); -} - -inline bool Registers_riscv::validRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return true; - if (regNum == UNW_REG_SP) - return true; - if (regNum < 0) - return false; - if (regNum > 95) - return false; - if ((regNum > 31) && (regNum < 64)) - return false; - return true; -} - -inline uint64_t Registers_riscv::getRegister(int regNum) const { - if (regNum == UNW_REG_IP) - return _registers.__x[1]; - if (regNum == UNW_REG_SP) - return _registers.__x[2]; - if ((regNum >= 0) && (regNum < 32)) - return _registers.__x[regNum]; - _LIBUNWIND_ABORT("unsupported riscv register"); -} - -inline void Registers_riscv::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP) - _registers.__x[1] = value; - else if (regNum == UNW_REG_SP) - _registers.__x[2] = value; - else if ((regNum >= 0) && (regNum < 32)) - _registers.__x[regNum] = value; - else - _LIBUNWIND_ABORT("unsupported riscv register"); -} - -inline const char *Registers_riscv::getRegisterName(int regNum) { - switch (regNum) { - case UNW_REG_IP: - return "ra"; - case UNW_REG_SP: - return "sp"; - case UNW_RISCV_X0: - return "x0"; - case UNW_RISCV_X1: - return "ra"; - case UNW_RISCV_X2: - return "sp"; - case UNW_RISCV_X3: - return "x3"; - case UNW_RISCV_X4: - return "x4"; - case UNW_RISCV_X5: - return "x5"; - case UNW_RISCV_X6: - return "x6"; - case UNW_RISCV_X7: - return "x7"; - case UNW_RISCV_X8: - return "x8"; - case UNW_RISCV_X9: - return "x9"; - case UNW_RISCV_X10: - return "x10"; - case UNW_RISCV_X11: - return "x11"; - case UNW_RISCV_X12: - return "x12"; - case UNW_RISCV_X13: - return "x13"; - case UNW_RISCV_X14: - return "x14"; - case UNW_RISCV_X15: - return "x15"; - case UNW_RISCV_X16: - return "x16"; - case UNW_RISCV_X17: - return "x17"; - case UNW_RISCV_X18: - return "x18"; - case UNW_RISCV_X19: - return "x19"; - case UNW_RISCV_X20: - return "x20"; - case UNW_RISCV_X21: - return "x21"; - case UNW_RISCV_X22: - return "x22"; - case UNW_RISCV_X23: - return "x23"; - case UNW_RISCV_X24: - return "x24"; - case UNW_RISCV_X25: - return "x25"; - case UNW_RISCV_X26: - return "x26"; - case UNW_RISCV_X27: - return "x27"; - case UNW_RISCV_X28: - return "x28"; - case UNW_RISCV_X29: - return "x29"; - case UNW_RISCV_X30: - return "x30"; - case UNW_RISCV_X31: - return "x31"; - case UNW_RISCV_D0: - return "d0"; - case UNW_RISCV_D1: - return "d1"; - case UNW_RISCV_D2: - return "d2"; - case UNW_RISCV_D3: - return "d3"; - case UNW_RISCV_D4: - return "d4"; - case UNW_RISCV_D5: - return "d5"; - case UNW_RISCV_D6: - return "d6"; - case UNW_RISCV_D7: - return "d7"; - case UNW_RISCV_D8: - return "d8"; - case UNW_RISCV_D9: - return "d9"; - case UNW_RISCV_D10: - return "d10"; - case UNW_RISCV_D11: - return "d11"; - case UNW_RISCV_D12: - return "d12"; - case UNW_RISCV_D13: - return "d13"; - case UNW_RISCV_D14: - return "d14"; - case UNW_RISCV_D15: - return "d15"; - case UNW_RISCV_D16: - return "d16"; - case UNW_RISCV_D17: - return "d17"; - case UNW_RISCV_D18: - return "d18"; - case UNW_RISCV_D19: - return "d19"; - case UNW_RISCV_D20: - return "d20"; - case UNW_RISCV_D21: - return "d21"; - case UNW_RISCV_D22: - return "d22"; - case UNW_RISCV_D23: - return "d23"; - case UNW_RISCV_D24: - return "d24"; - case UNW_RISCV_D25: - return "d25"; - case UNW_RISCV_D26: - return "d26"; - case UNW_RISCV_D27: - return "d27"; - case UNW_RISCV_D28: - return "d28"; - case UNW_RISCV_D29: - return "d29"; - case UNW_RISCV_D30: - return "d30"; - case UNW_RISCV_D31: - return "d31"; - default: - return "unknown register"; - } -} - -inline bool Registers_riscv::validFloatRegister(int regNum) const { - if (regNum < UNW_RISCV_D0) - return false; - if (regNum > UNW_RISCV_D31) - return false; - return true; -} - -inline double Registers_riscv::getFloatRegister(int regNum) const { - assert(validFloatRegister(regNum)); - return _vectorHalfRegisters[regNum - UNW_RISCV_D0]; -} - -inline void Registers_riscv::setFloatRegister(int regNum, double value) { - assert(validFloatRegister(regNum)); - _vectorHalfRegisters[regNum - UNW_RISCV_D0] = value; -} - -inline bool Registers_riscv::validVectorRegister(int) const { - return false; -} - -inline v128 Registers_riscv::getVectorRegister(int) const { - _LIBUNWIND_ABORT("no riscv vector register support yet"); -} - -inline void Registers_riscv::setVectorRegister(int, v128) { - _LIBUNWIND_ABORT("no riscv vector register support yet"); -} -#endif // _LIBUNWIND_TARGET_RISCV #if defined(_LIBUNWIND_TARGET_MIPS_O32) /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS /// process. class _LIBUNWIND_HIDDEN Registers_mips_o32 { public: Registers_mips_o32(); Registers_mips_o32(const void *registers); bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } static int getArch() { return REGISTERS_MIPS_O32; } uint32_t getSP() const { return _registers.__r[29]; } void setSP(uint32_t value) { _registers.__r[29] = value; } uint32_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } private: struct mips_o32_thread_state_t { uint32_t __r[32]; uint32_t __pc; uint32_t __hi; uint32_t __lo; }; mips_o32_thread_state_t _registers; #ifdef __mips_hard_float /// O32 with 32-bit floating point registers only uses half of this /// space. However, using the same layout for 32-bit vs 64-bit /// floating point registers results in a single context size for /// O32 with hard float. uint32_t _padding; double _floats[32]; #endif }; inline Registers_mips_o32::Registers_mips_o32(const void *registers) { static_assert((check_fit::does_fit), "mips_o32 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } inline Registers_mips_o32::Registers_mips_o32() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_mips_o32::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum <= UNW_MIPS_R31) return true; #if __mips_isa_rev != 6 if (regNum == UNW_MIPS_HI) return true; if (regNum == UNW_MIPS_LO) return true; #endif #if defined(__mips_hard_float) && __mips_fpr == 32 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) return true; #endif // FIXME: DSP accumulator registers, MSA registers return false; } inline uint32_t Registers_mips_o32::getRegister(int regNum) const { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) return _registers.__r[regNum - UNW_MIPS_R0]; #if defined(__mips_hard_float) && __mips_fpr == 32 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { uint32_t *p; if (regNum % 2 == 0) p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; else p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; return *p; } #endif switch (regNum) { case UNW_REG_IP: return _registers.__pc; case UNW_REG_SP: return _registers.__r[29]; case UNW_MIPS_HI: return _registers.__hi; case UNW_MIPS_LO: return _registers.__lo; } _LIBUNWIND_ABORT("unsupported mips_o32 register"); } inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { _registers.__r[regNum - UNW_MIPS_R0] = value; return; } #if defined(__mips_hard_float) && __mips_fpr == 32 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { uint32_t *p; if (regNum % 2 == 0) p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; else p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; *p = value; return; } #endif switch (regNum) { case UNW_REG_IP: _registers.__pc = value; return; case UNW_REG_SP: _registers.__r[29] = value; return; case UNW_MIPS_HI: _registers.__hi = value; return; case UNW_MIPS_LO: _registers.__lo = value; return; } _LIBUNWIND_ABORT("unsupported mips_o32 register"); } inline bool Registers_mips_o32::validFloatRegister(int regNum) const { #if defined(__mips_hard_float) && __mips_fpr == 64 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) return true; #endif return false; } inline double Registers_mips_o32::getFloatRegister(int regNum) const { #if defined(__mips_hard_float) && __mips_fpr == 64 assert(validFloatRegister(regNum)); return _floats[regNum - UNW_MIPS_F0]; #else _LIBUNWIND_ABORT("mips_o32 float support not implemented"); #endif } inline void Registers_mips_o32::setFloatRegister(int regNum, double value) { #if defined(__mips_hard_float) && __mips_fpr == 64 assert(validFloatRegister(regNum)); _floats[regNum - UNW_MIPS_F0] = value; #else _LIBUNWIND_ABORT("mips_o32 float support not implemented"); #endif } inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const { return false; } inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const { _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); } inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) { _LIBUNWIND_ABORT("mips_o32 vector support not implemented"); } inline const char *Registers_mips_o32::getRegisterName(int regNum) { switch (regNum) { case UNW_MIPS_R0: return "$0"; case UNW_MIPS_R1: return "$1"; case UNW_MIPS_R2: return "$2"; case UNW_MIPS_R3: return "$3"; case UNW_MIPS_R4: return "$4"; case UNW_MIPS_R5: return "$5"; case UNW_MIPS_R6: return "$6"; case UNW_MIPS_R7: return "$7"; case UNW_MIPS_R8: return "$8"; case UNW_MIPS_R9: return "$9"; case UNW_MIPS_R10: return "$10"; case UNW_MIPS_R11: return "$11"; case UNW_MIPS_R12: return "$12"; case UNW_MIPS_R13: return "$13"; case UNW_MIPS_R14: return "$14"; case UNW_MIPS_R15: return "$15"; case UNW_MIPS_R16: return "$16"; case UNW_MIPS_R17: return "$17"; case UNW_MIPS_R18: return "$18"; case UNW_MIPS_R19: return "$19"; case UNW_MIPS_R20: return "$20"; case UNW_MIPS_R21: return "$21"; case UNW_MIPS_R22: return "$22"; case UNW_MIPS_R23: return "$23"; case UNW_MIPS_R24: return "$24"; case UNW_MIPS_R25: return "$25"; case UNW_MIPS_R26: return "$26"; case UNW_MIPS_R27: return "$27"; case UNW_MIPS_R28: return "$28"; case UNW_MIPS_R29: return "$29"; case UNW_MIPS_R30: return "$30"; case UNW_MIPS_R31: return "$31"; case UNW_MIPS_F0: return "$f0"; case UNW_MIPS_F1: return "$f1"; case UNW_MIPS_F2: return "$f2"; case UNW_MIPS_F3: return "$f3"; case UNW_MIPS_F4: return "$f4"; case UNW_MIPS_F5: return "$f5"; case UNW_MIPS_F6: return "$f6"; case UNW_MIPS_F7: return "$f7"; case UNW_MIPS_F8: return "$f8"; case UNW_MIPS_F9: return "$f9"; case UNW_MIPS_F10: return "$f10"; case UNW_MIPS_F11: return "$f11"; case UNW_MIPS_F12: return "$f12"; case UNW_MIPS_F13: return "$f13"; case UNW_MIPS_F14: return "$f14"; case UNW_MIPS_F15: return "$f15"; case UNW_MIPS_F16: return "$f16"; case UNW_MIPS_F17: return "$f17"; case UNW_MIPS_F18: return "$f18"; case UNW_MIPS_F19: return "$f19"; case UNW_MIPS_F20: return "$f20"; case UNW_MIPS_F21: return "$f21"; case UNW_MIPS_F22: return "$f22"; case UNW_MIPS_F23: return "$f23"; case UNW_MIPS_F24: return "$f24"; case UNW_MIPS_F25: return "$f25"; case UNW_MIPS_F26: return "$f26"; case UNW_MIPS_F27: return "$f27"; case UNW_MIPS_F28: return "$f28"; case UNW_MIPS_F29: return "$f29"; case UNW_MIPS_F30: return "$f30"; case UNW_MIPS_F31: return "$f31"; case UNW_MIPS_HI: return "$hi"; case UNW_MIPS_LO: return "$lo"; default: return "unknown register"; } } #endif // _LIBUNWIND_TARGET_MIPS_O32 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) /// Registers_mips_newabi holds the register state of a thread in a /// MIPS process using NEWABI (the N32 or N64 ABIs). class _LIBUNWIND_HIDDEN Registers_mips_newabi { public: Registers_mips_newabi(); Registers_mips_newabi(const void *registers); bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } static int getArch() { return REGISTERS_MIPS_NEWABI; } uint64_t getSP() const { return _registers.__r[29]; } void setSP(uint64_t value) { _registers.__r[29] = value; } uint64_t getIP() const { return _registers.__pc; } void setIP(uint64_t value) { _registers.__pc = value; } private: struct mips_newabi_thread_state_t { uint64_t __r[32]; uint64_t __pc; uint64_t __hi; uint64_t __lo; }; mips_newabi_thread_state_t _registers; #ifdef __mips_hard_float double _floats[32]; #endif }; inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { static_assert((check_fit::does_fit), "mips_newabi registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } inline Registers_mips_newabi::Registers_mips_newabi() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_mips_newabi::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum <= UNW_MIPS_R31) return true; #if __mips_isa_rev != 6 if (regNum == UNW_MIPS_HI) return true; if (regNum == UNW_MIPS_LO) return true; #endif // FIXME: Hard float, DSP accumulator registers, MSA registers return false; } inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) return _registers.__r[regNum - UNW_MIPS_R0]; switch (regNum) { case UNW_REG_IP: return _registers.__pc; case UNW_REG_SP: return _registers.__r[29]; case UNW_MIPS_HI: return _registers.__hi; case UNW_MIPS_LO: return _registers.__lo; } _LIBUNWIND_ABORT("unsupported mips_newabi register"); } inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { _registers.__r[regNum - UNW_MIPS_R0] = value; return; } switch (regNum) { case UNW_REG_IP: _registers.__pc = value; return; case UNW_REG_SP: _registers.__r[29] = value; return; case UNW_MIPS_HI: _registers.__hi = value; return; case UNW_MIPS_LO: _registers.__lo = value; return; } _LIBUNWIND_ABORT("unsupported mips_newabi register"); } inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { #ifdef __mips_hard_float if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) return true; #endif return false; } inline double Registers_mips_newabi::getFloatRegister(int regNum) const { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); return _floats[regNum - UNW_MIPS_F0]; #else _LIBUNWIND_ABORT("mips_newabi float support not implemented"); #endif } inline void Registers_mips_newabi::setFloatRegister(int regNum, double value) { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); _floats[regNum - UNW_MIPS_F0] = value; #else _LIBUNWIND_ABORT("mips_newabi float support not implemented"); #endif } inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const { return false; } inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const { _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); } inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) { _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); } inline const char *Registers_mips_newabi::getRegisterName(int regNum) { switch (regNum) { case UNW_MIPS_R0: return "$0"; case UNW_MIPS_R1: return "$1"; case UNW_MIPS_R2: return "$2"; case UNW_MIPS_R3: return "$3"; case UNW_MIPS_R4: return "$4"; case UNW_MIPS_R5: return "$5"; case UNW_MIPS_R6: return "$6"; case UNW_MIPS_R7: return "$7"; case UNW_MIPS_R8: return "$8"; case UNW_MIPS_R9: return "$9"; case UNW_MIPS_R10: return "$10"; case UNW_MIPS_R11: return "$11"; case UNW_MIPS_R12: return "$12"; case UNW_MIPS_R13: return "$13"; case UNW_MIPS_R14: return "$14"; case UNW_MIPS_R15: return "$15"; case UNW_MIPS_R16: return "$16"; case UNW_MIPS_R17: return "$17"; case UNW_MIPS_R18: return "$18"; case UNW_MIPS_R19: return "$19"; case UNW_MIPS_R20: return "$20"; case UNW_MIPS_R21: return "$21"; case UNW_MIPS_R22: return "$22"; case UNW_MIPS_R23: return "$23"; case UNW_MIPS_R24: return "$24"; case UNW_MIPS_R25: return "$25"; case UNW_MIPS_R26: return "$26"; case UNW_MIPS_R27: return "$27"; case UNW_MIPS_R28: return "$28"; case UNW_MIPS_R29: return "$29"; case UNW_MIPS_R30: return "$30"; case UNW_MIPS_R31: return "$31"; case UNW_MIPS_F0: return "$f0"; case UNW_MIPS_F1: return "$f1"; case UNW_MIPS_F2: return "$f2"; case UNW_MIPS_F3: return "$f3"; case UNW_MIPS_F4: return "$f4"; case UNW_MIPS_F5: return "$f5"; case UNW_MIPS_F6: return "$f6"; case UNW_MIPS_F7: return "$f7"; case UNW_MIPS_F8: return "$f8"; case UNW_MIPS_F9: return "$f9"; case UNW_MIPS_F10: return "$f10"; case UNW_MIPS_F11: return "$f11"; case UNW_MIPS_F12: return "$f12"; case UNW_MIPS_F13: return "$f13"; case UNW_MIPS_F14: return "$f14"; case UNW_MIPS_F15: return "$f15"; case UNW_MIPS_F16: return "$f16"; case UNW_MIPS_F17: return "$f17"; case UNW_MIPS_F18: return "$f18"; case UNW_MIPS_F19: return "$f19"; case UNW_MIPS_F20: return "$f20"; case UNW_MIPS_F21: return "$f21"; case UNW_MIPS_F22: return "$f22"; case UNW_MIPS_F23: return "$f23"; case UNW_MIPS_F24: return "$f24"; case UNW_MIPS_F25: return "$f25"; case UNW_MIPS_F26: return "$f26"; case UNW_MIPS_F27: return "$f27"; case UNW_MIPS_F28: return "$f28"; case UNW_MIPS_F29: return "$f29"; case UNW_MIPS_F30: return "$f30"; case UNW_MIPS_F31: return "$f31"; case UNW_MIPS_HI: return "$hi"; case UNW_MIPS_LO: return "$lo"; default: return "unknown register"; } } #endif // _LIBUNWIND_TARGET_MIPS_NEWABI #if defined(_LIBUNWIND_TARGET_SPARC) /// Registers_sparc holds the register state of a thread in a 32-bit Sparc /// process. class _LIBUNWIND_HIDDEN Registers_sparc { public: Registers_sparc(); Registers_sparc(const void *registers); bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; } static int getArch() { return REGISTERS_SPARC; } uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; } void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; } uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; } private: struct sparc_thread_state_t { unsigned int __regs[32]; }; sparc_thread_state_t _registers; }; inline Registers_sparc::Registers_sparc(const void *registers) { static_assert((check_fit::does_fit), "sparc registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } inline Registers_sparc::Registers_sparc() { memset(&_registers, 0, sizeof(_registers)); } inline bool Registers_sparc::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum <= UNW_SPARC_I7) return true; return false; } inline uint32_t Registers_sparc::getRegister(int regNum) const { if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { return _registers.__regs[regNum]; } switch (regNum) { case UNW_REG_IP: return _registers.__regs[UNW_SPARC_O7]; case UNW_REG_SP: return _registers.__regs[UNW_SPARC_O6]; } _LIBUNWIND_ABORT("unsupported sparc register"); } inline void Registers_sparc::setRegister(int regNum, uint32_t value) { if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { _registers.__regs[regNum] = value; return; } switch (regNum) { case UNW_REG_IP: _registers.__regs[UNW_SPARC_O7] = value; return; case UNW_REG_SP: _registers.__regs[UNW_SPARC_O6] = value; return; } _LIBUNWIND_ABORT("unsupported sparc register"); } inline bool Registers_sparc::validFloatRegister(int) const { return false; } inline double Registers_sparc::getFloatRegister(int) const { _LIBUNWIND_ABORT("no Sparc float registers"); } inline void Registers_sparc::setFloatRegister(int, double) { _LIBUNWIND_ABORT("no Sparc float registers"); } inline bool Registers_sparc::validVectorRegister(int) const { return false; } inline v128 Registers_sparc::getVectorRegister(int) const { _LIBUNWIND_ABORT("no Sparc vector registers"); } inline void Registers_sparc::setVectorRegister(int, v128) { _LIBUNWIND_ABORT("no Sparc vector registers"); } inline const char *Registers_sparc::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "pc"; case UNW_SPARC_G0: return "g0"; case UNW_SPARC_G1: return "g1"; case UNW_SPARC_G2: return "g2"; case UNW_SPARC_G3: return "g3"; case UNW_SPARC_G4: return "g4"; case UNW_SPARC_G5: return "g5"; case UNW_SPARC_G6: return "g6"; case UNW_SPARC_G7: return "g7"; case UNW_SPARC_O0: return "o0"; case UNW_SPARC_O1: return "o1"; case UNW_SPARC_O2: return "o2"; case UNW_SPARC_O3: return "o3"; case UNW_SPARC_O4: return "o4"; case UNW_SPARC_O5: return "o5"; case UNW_REG_SP: case UNW_SPARC_O6: return "sp"; case UNW_SPARC_O7: return "o7"; case UNW_SPARC_L0: return "l0"; case UNW_SPARC_L1: return "l1"; case UNW_SPARC_L2: return "l2"; case UNW_SPARC_L3: return "l3"; case UNW_SPARC_L4: return "l4"; case UNW_SPARC_L5: return "l5"; case UNW_SPARC_L6: return "l6"; case UNW_SPARC_L7: return "l7"; case UNW_SPARC_I0: return "i0"; case UNW_SPARC_I1: return "i1"; case UNW_SPARC_I2: return "i2"; case UNW_SPARC_I3: return "i3"; case UNW_SPARC_I4: return "i4"; case UNW_SPARC_I5: return "i5"; case UNW_SPARC_I6: return "fp"; case UNW_SPARC_I7: return "i7"; default: return "unknown register"; } } #endif // _LIBUNWIND_TARGET_SPARC #if defined(_LIBUNWIND_TARGET_RISCV) /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V /// process. class _LIBUNWIND_HIDDEN Registers_riscv { public: Registers_riscv(); Registers_riscv(const void *registers); bool validRegister(int num) const; uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } static int getArch() { return REGISTERS_RISCV; } uint64_t getSP() const { return _registers[2]; } void setSP(uint64_t value) { _registers[2] = value; } uint64_t getIP() const { return _registers[1]; } void setIP(uint64_t value) { _registers[1] = value; } private: uint64_t _registers[32]; double _floats[32]; }; 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)); static_assert(sizeof(_registers) == 0x100, "expected float registers to be at offset 256"); memcpy(_floats, static_cast(registers) + sizeof(_registers), sizeof(_floats)); } inline Registers_riscv::Registers_riscv() { memset(&_registers, 0, sizeof(_registers)); memset(&_floats, 0, sizeof(_floats)); } inline bool Registers_riscv::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) return true; if (regNum < 0) return false; if (regNum > UNW_RISCV_F31) return false; return true; } inline uint64_t Registers_riscv::getRegister(int regNum) const { if (regNum == UNW_REG_IP) return _registers[1]; if (regNum == UNW_REG_SP) return _registers[2]; if (regNum == UNW_RISCV_X0) return 0; if ((regNum > 0) && (regNum < 32)) return _registers[regNum]; _LIBUNWIND_ABORT("unsupported riscv register"); } inline void Registers_riscv::setRegister(int regNum, uint64_t value) { if (regNum == UNW_REG_IP) _registers[1] = 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)) _registers[regNum] = value; else _LIBUNWIND_ABORT("unsupported riscv register"); } inline const char *Registers_riscv::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: return "pc"; case UNW_REG_SP: return "sp"; case UNW_RISCV_X0: return "zero"; case UNW_RISCV_X1: return "ra"; case UNW_RISCV_X2: return "sp"; case UNW_RISCV_X3: return "gp"; case UNW_RISCV_X4: return "tp"; case UNW_RISCV_X5: return "t0"; case UNW_RISCV_X6: return "t1"; case UNW_RISCV_X7: return "t2"; case UNW_RISCV_X8: return "s0"; case UNW_RISCV_X9: return "s1"; case UNW_RISCV_X10: return "a0"; case UNW_RISCV_X11: return "a1"; case UNW_RISCV_X12: return "a2"; case UNW_RISCV_X13: return "a3"; case UNW_RISCV_X14: return "a4"; case UNW_RISCV_X15: return "a5"; case UNW_RISCV_X16: return "a6"; case UNW_RISCV_X17: return "a7"; case UNW_RISCV_X18: return "s2"; case UNW_RISCV_X19: return "s3"; case UNW_RISCV_X20: return "s4"; case UNW_RISCV_X21: return "s5"; case UNW_RISCV_X22: return "s6"; case UNW_RISCV_X23: return "s7"; case UNW_RISCV_X24: return "s8"; case UNW_RISCV_X25: return "s9"; case UNW_RISCV_X26: return "s10"; case UNW_RISCV_X27: return "s11"; case UNW_RISCV_X28: return "t3"; case UNW_RISCV_X29: return "t4"; case UNW_RISCV_X30: return "t5"; case UNW_RISCV_X31: return "t6"; case UNW_RISCV_F0: return "ft0"; case UNW_RISCV_F1: return "ft1"; case UNW_RISCV_F2: return "ft2"; case UNW_RISCV_F3: return "ft3"; case UNW_RISCV_F4: return "ft4"; case UNW_RISCV_F5: return "ft5"; case UNW_RISCV_F6: return "ft6"; case UNW_RISCV_F7: return "ft7"; case UNW_RISCV_F8: return "fs0"; case UNW_RISCV_F9: return "fs1"; case UNW_RISCV_F10: return "fa0"; case UNW_RISCV_F11: return "fa1"; case UNW_RISCV_F12: return "fa2"; case UNW_RISCV_F13: return "fa3"; case UNW_RISCV_F14: return "fa4"; case UNW_RISCV_F15: return "fa5"; case UNW_RISCV_F16: return "fa6"; case UNW_RISCV_F17: return "fa7"; case UNW_RISCV_F18: return "fs2"; case UNW_RISCV_F19: return "fs3"; case UNW_RISCV_F20: return "fs4"; case UNW_RISCV_F21: return "fs5"; case UNW_RISCV_F22: return "fs6"; case UNW_RISCV_F23: return "fs7"; case UNW_RISCV_F24: return "fs8"; case UNW_RISCV_F25: return "fs9"; case UNW_RISCV_F26: return "fs10"; case UNW_RISCV_F27: return "fs11"; case UNW_RISCV_F28: return "ft8"; case UNW_RISCV_F29: return "ft9"; case UNW_RISCV_F30: return "ft10"; case UNW_RISCV_F31: return "ft11"; default: return "unknown register"; } } inline bool Registers_riscv::validFloatRegister(int regNum) const { if (regNum < UNW_RISCV_F0) return false; if (regNum > UNW_RISCV_F31) return false; return true; } inline double Registers_riscv::getFloatRegister(int regNum) const { #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); return _floats[regNum - UNW_RISCV_F0]; #else _LIBUNWIND_ABORT("libunwind not built with float support"); #endif } inline void Registers_riscv::setFloatRegister(int regNum, double value) { #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); _floats[regNum - UNW_RISCV_F0] = value; #else _LIBUNWIND_ABORT("libunwind not built with float support"); #endif } inline bool Registers_riscv::validVectorRegister(int) const { return false; } inline v128 Registers_riscv::getVectorRegister(int) const { _LIBUNWIND_ABORT("no riscv vector register support yet"); } inline void Registers_riscv::setVectorRegister(int, v128) { _LIBUNWIND_ABORT("no riscv vector register support yet"); } #endif // _LIBUNWIND_TARGET_RISCV } // namespace libunwind #endif // __REGISTERS_HPP__ Index: projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindCursor.hpp =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindCursor.hpp (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindCursor.hpp (revision 357209) @@ -1,2028 +1,2022 @@ //===------------------------- UnwindCursor.hpp ---------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // // C++ interface to lower levels of libunwind //===----------------------------------------------------------------------===// #ifndef __UNWINDCURSOR_HPP__ #define __UNWINDCURSOR_HPP__ #include #include #include #include #ifdef _WIN32 #include #include #endif #ifdef __APPLE__ #include #endif #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and // earlier) SDKs. // MinGW-w64 has always provided this struct. #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \ !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 struct _DISPATCHER_CONTEXT { ULONG64 ControlPc; ULONG64 ImageBase; PRUNTIME_FUNCTION FunctionEntry; ULONG64 EstablisherFrame; ULONG64 TargetIp; PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; PUNWIND_HISTORY_TABLE HistoryTable; ULONG ScopeIndex; ULONG Fill0; }; #endif struct UNWIND_INFO { uint8_t Version : 3; uint8_t Flags : 5; uint8_t SizeOfProlog; uint8_t CountOfCodes; uint8_t FrameRegister : 4; uint8_t FrameOffset : 4; uint16_t UnwindCodes[2]; }; extern "C" _Unwind_Reason_Code __libunwind_seh_personality( int, _Unwind_Action, uint64_t, _Unwind_Exception *, struct _Unwind_Context *); #endif #include "config.h" #include "AddressSpace.hpp" #include "CompactUnwinder.hpp" #include "config.h" #include "DwarfInstructions.hpp" #include "EHHeaderParser.hpp" #include "libunwind.h" #include "Registers.hpp" #include "RWMutex.hpp" #include "Unwind-EHABI.h" namespace libunwind { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) /// Cache of recently found FDEs. template class _LIBUNWIND_HIDDEN DwarfFDECache { typedef typename A::pint_t pint_t; public: static pint_t findFDE(pint_t mh, pint_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, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)); private: struct entry { pint_t mh; pint_t ip_start; pint_t ip_end; pint_t fde; }; // These fields are all static to avoid needing an initializer. // There is only one instance of this class per process. static RWMutex _lock; #ifdef __APPLE__ static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); static bool _registeredForDyldUnloads; #endif static entry *_buffer; static entry *_bufferUsed; static entry *_bufferEnd; static entry _initialBuffer[64]; }; template typename DwarfFDECache::entry * DwarfFDECache::_buffer = _initialBuffer; template typename DwarfFDECache::entry * DwarfFDECache::_bufferUsed = _initialBuffer; template typename DwarfFDECache::entry * DwarfFDECache::_bufferEnd = &_initialBuffer[64]; template typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64]; template RWMutex DwarfFDECache::_lock; #ifdef __APPLE__ template bool DwarfFDECache::_registeredForDyldUnloads = false; #endif template typename A::pint_t DwarfFDECache::findFDE(pint_t mh, pint_t pc) { pint_t result = 0; _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { if ((mh == p->mh) || (mh == 0)) { if ((p->ip_start <= pc) && (pc < p->ip_end)) { result = p->fde; break; } } } _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); return result; } template void DwarfFDECache::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde) { #if !defined(_LIBUNWIND_NO_HEAP) _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); if (_bufferUsed >= _bufferEnd) { size_t oldSize = (size_t)(_bufferEnd - _buffer); size_t newSize = oldSize * 4; // Can't use operator new (we are below it). entry *newBuffer = (entry *)malloc(newSize * sizeof(entry)); memcpy(newBuffer, _buffer, oldSize * sizeof(entry)); if (_buffer != _initialBuffer) free(_buffer); _buffer = newBuffer; _bufferUsed = &newBuffer[oldSize]; _bufferEnd = &newBuffer[newSize]; } _bufferUsed->mh = mh; _bufferUsed->ip_start = ip_start; _bufferUsed->ip_end = ip_end; _bufferUsed->fde = fde; ++_bufferUsed; #ifdef __APPLE__ if (!_registeredForDyldUnloads) { _dyld_register_func_for_remove_image(&dyldUnloadHook); _registeredForDyldUnloads = true; } #endif _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); #endif } template void DwarfFDECache::removeAllIn(pint_t mh) { _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); entry *d = _buffer; for (const entry *s = _buffer; s < _bufferUsed; ++s) { if (s->mh != mh) { if (d != s) *d = *s; ++d; } } _bufferUsed = d; _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #ifdef __APPLE__ template void DwarfFDECache::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { removeAllIn((pint_t) mh); } #endif template void DwarfFDECache::iterateCacheEntries(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); for (entry *p = _buffer; p < _bufferUsed; ++p) { (*func)(p->ip_start, p->ip_end, p->fde, p->mh); } _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template class UnwindSectionHeader { public: UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t version() const { return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, version)); } uint32_t commonEncodingsArraySectionOffset() const { return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, commonEncodingsArraySectionOffset)); } uint32_t commonEncodingsArrayCount() const { return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, commonEncodingsArrayCount)); } uint32_t personalityArraySectionOffset() const { return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, personalityArraySectionOffset)); } uint32_t personalityArrayCount() const { return _addressSpace.get32( _addr + offsetof(unwind_info_section_header, personalityArrayCount)); } uint32_t indexSectionOffset() const { return _addressSpace.get32( _addr + offsetof(unwind_info_section_header, indexSectionOffset)); } uint32_t indexCount() const { return _addressSpace.get32( _addr + offsetof(unwind_info_section_header, indexCount)); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionIndexArray { public: UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t functionOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, functionOffset)); } uint32_t secondLevelPagesSectionOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, secondLevelPagesSectionOffset)); } uint32_t lsdaIndexArraySectionOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, lsdaIndexArraySectionOffset)); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionRegularPageHeader { public: UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t kind() const { return _addressSpace.get32( _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); } uint16_t entryPageOffset() const { return _addressSpace.get16( _addr + offsetof(unwind_info_regular_second_level_page_header, entryPageOffset)); } uint16_t entryCount() const { return _addressSpace.get16( _addr + offsetof(unwind_info_regular_second_level_page_header, entryCount)); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionRegularArray { public: UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t functionOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, functionOffset)); } uint32_t encoding(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionCompressedPageHeader { public: UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t kind() const { return _addressSpace.get32( _addr + offsetof(unwind_info_compressed_second_level_page_header, kind)); } uint16_t entryPageOffset() const { return _addressSpace.get16( _addr + offsetof(unwind_info_compressed_second_level_page_header, entryPageOffset)); } uint16_t entryCount() const { return _addressSpace.get16( _addr + offsetof(unwind_info_compressed_second_level_page_header, entryCount)); } uint16_t encodingsPageOffset() const { return _addressSpace.get16( _addr + offsetof(unwind_info_compressed_second_level_page_header, encodingsPageOffset)); } uint16_t encodingsCount() const { return _addressSpace.get16( _addr + offsetof(unwind_info_compressed_second_level_page_header, encodingsCount)); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionCompressedArray { public: UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t functionOffset(uint32_t index) const { return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( _addressSpace.get32(_addr + index * sizeof(uint32_t))); } uint16_t encodingIndex(uint32_t index) const { return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( _addressSpace.get32(_addr + index * sizeof(uint32_t))); } private: A &_addressSpace; typename A::pint_t _addr; }; template class UnwindSectionLsdaArray { public: UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) : _addressSpace(addressSpace), _addr(addr) {} uint32_t functionOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, functionOffset)); } uint32_t lsdaOffset(uint32_t index) const { return _addressSpace.get32( _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, lsdaOffset)); } private: A &_addressSpace; typename A::pint_t _addr; }; #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) class _LIBUNWIND_HIDDEN AbstractUnwindCursor { public: // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) // This avoids an unnecessary dependency to libc++abi. void operator delete(void *, size_t) {} 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) { _LIBUNWIND_ABORT("setReg not implemented"); } virtual bool validFloatReg(int) { _LIBUNWIND_ABORT("validFloatReg not implemented"); } virtual unw_fpreg_t getFloatReg(int) { _LIBUNWIND_ABORT("getFloatReg not implemented"); } virtual void setFloatReg(int, unw_fpreg_t) { _LIBUNWIND_ABORT("setFloatReg not implemented"); } virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } virtual void getInfo(unw_proc_info_t *) { _LIBUNWIND_ABORT("getInfo not implemented"); } virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } virtual bool isSignalFrame() { _LIBUNWIND_ABORT("isSignalFrame not implemented"); } virtual bool getFunctionName(char *, size_t, unw_word_t *) { _LIBUNWIND_ABORT("getFunctionName not implemented"); } virtual void setInfoBasedOnIPRegister(bool = false) { _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); } virtual const char *getRegisterName(int) { _LIBUNWIND_ABORT("getRegisterName not implemented"); } #ifdef __arm__ virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } #endif }; #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) /// \c UnwindCursor contains all state (including all register values) during /// an unwind. This is normally stack-allocated inside a unw_cursor_t. template class UnwindCursor : public AbstractUnwindCursor { typedef typename A::pint_t pint_t; public: UnwindCursor(unw_context_t *context, A &as); UnwindCursor(CONTEXT *context, A &as); UnwindCursor(A &as, void *threadArg); virtual ~UnwindCursor() {} virtual bool validReg(int); virtual unw_word_t getReg(int); virtual void setReg(int, unw_word_t); virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); virtual int step(); virtual void getInfo(unw_proc_info_t *); virtual void jumpto(); virtual bool isSignalFrame(); virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); virtual const char *getRegisterName(int num); #ifdef __arm__ virtual void saveVFPAsX(); #endif DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } // libunwind does not and should not depend on C++ library which means that we // need our own defition of inline placement new. static void *operator new(size_t, UnwindCursor *p) { return p; } private: pint_t getLastPC() const { return _dispContext.ControlPc; } void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; } RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc, &_dispContext.ImageBase, _dispContext.HistoryTable); *base = _dispContext.ImageBase; return _dispContext.FunctionEntry; } bool getInfoFromSEH(pint_t pc); int stepWithSEHData() { _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER, _dispContext.ImageBase, _dispContext.ControlPc, _dispContext.FunctionEntry, _dispContext.ContextRecord, &_dispContext.HandlerData, &_dispContext.EstablisherFrame, NULL); // Update some fields of the unwind info now, since we have them. _info.lsda = reinterpret_cast(_dispContext.HandlerData); if (_dispContext.LanguageHandler) { _info.handler = reinterpret_cast(__libunwind_seh_personality); } else _info.handler = 0; return UNW_STEP_SUCCESS; } A &_addressSpace; unw_proc_info_t _info; DISPATCHER_CONTEXT _dispContext; CONTEXT _msContext; UNWIND_HISTORY_TABLE _histTable; bool _unwindInfoMissing; }; template UnwindCursor::UnwindCursor(unw_context_t *context, A &as) : _addressSpace(as), _unwindInfoMissing(false) { static_assert((check_fit, unw_cursor_t>::does_fit), "UnwindCursor<> does not fit in unw_cursor_t"); memset(&_info, 0, sizeof(_info)); memset(&_histTable, 0, sizeof(_histTable)); _dispContext.ContextRecord = &_msContext; _dispContext.HistoryTable = &_histTable; // Initialize MS context from ours. R r(context); _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT; #if defined(_LIBUNWIND_TARGET_X86_64) _msContext.Rax = r.getRegister(UNW_X86_64_RAX); _msContext.Rcx = r.getRegister(UNW_X86_64_RCX); _msContext.Rdx = r.getRegister(UNW_X86_64_RDX); _msContext.Rbx = r.getRegister(UNW_X86_64_RBX); _msContext.Rsp = r.getRegister(UNW_X86_64_RSP); _msContext.Rbp = r.getRegister(UNW_X86_64_RBP); _msContext.Rsi = r.getRegister(UNW_X86_64_RSI); _msContext.Rdi = r.getRegister(UNW_X86_64_RDI); _msContext.R8 = r.getRegister(UNW_X86_64_R8); _msContext.R9 = r.getRegister(UNW_X86_64_R9); _msContext.R10 = r.getRegister(UNW_X86_64_R10); _msContext.R11 = r.getRegister(UNW_X86_64_R11); _msContext.R12 = r.getRegister(UNW_X86_64_R12); _msContext.R13 = r.getRegister(UNW_X86_64_R13); _msContext.R14 = r.getRegister(UNW_X86_64_R14); _msContext.R15 = r.getRegister(UNW_X86_64_R15); _msContext.Rip = r.getRegister(UNW_REG_IP); union { v128 v; M128A m; } t; t.v = r.getVectorRegister(UNW_X86_64_XMM0); _msContext.Xmm0 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM1); _msContext.Xmm1 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM2); _msContext.Xmm2 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM3); _msContext.Xmm3 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM4); _msContext.Xmm4 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM5); _msContext.Xmm5 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM6); _msContext.Xmm6 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM7); _msContext.Xmm7 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM8); _msContext.Xmm8 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM9); _msContext.Xmm9 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM10); _msContext.Xmm10 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM11); _msContext.Xmm11 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM12); _msContext.Xmm12 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM13); _msContext.Xmm13 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM14); _msContext.Xmm14 = t.m; t.v = r.getVectorRegister(UNW_X86_64_XMM15); _msContext.Xmm15 = t.m; #elif defined(_LIBUNWIND_TARGET_ARM) _msContext.R0 = r.getRegister(UNW_ARM_R0); _msContext.R1 = r.getRegister(UNW_ARM_R1); _msContext.R2 = r.getRegister(UNW_ARM_R2); _msContext.R3 = r.getRegister(UNW_ARM_R3); _msContext.R4 = r.getRegister(UNW_ARM_R4); _msContext.R5 = r.getRegister(UNW_ARM_R5); _msContext.R6 = r.getRegister(UNW_ARM_R6); _msContext.R7 = r.getRegister(UNW_ARM_R7); _msContext.R8 = r.getRegister(UNW_ARM_R8); _msContext.R9 = r.getRegister(UNW_ARM_R9); _msContext.R10 = r.getRegister(UNW_ARM_R10); _msContext.R11 = r.getRegister(UNW_ARM_R11); _msContext.R12 = r.getRegister(UNW_ARM_R12); _msContext.Sp = r.getRegister(UNW_ARM_SP); _msContext.Lr = r.getRegister(UNW_ARM_LR); _msContext.Pc = r.getRegister(UNW_ARM_IP); for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) { union { uint64_t w; double d; } d; d.d = r.getFloatRegister(i); _msContext.D[i - UNW_ARM_D0] = d.w; } #elif defined(_LIBUNWIND_TARGET_AARCH64) for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); _msContext.Sp = r.getRegister(UNW_REG_SP); _msContext.Pc = r.getRegister(UNW_REG_IP); for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); #endif } template UnwindCursor::UnwindCursor(CONTEXT *context, A &as) : _addressSpace(as), _unwindInfoMissing(false) { static_assert((check_fit, unw_cursor_t>::does_fit), "UnwindCursor<> does not fit in unw_cursor_t"); memset(&_info, 0, sizeof(_info)); memset(&_histTable, 0, sizeof(_histTable)); _dispContext.ContextRecord = &_msContext; _dispContext.HistoryTable = &_histTable; _msContext = *context; } template bool UnwindCursor::validReg(int regNum) { if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true; #if defined(_LIBUNWIND_TARGET_X86_64) if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; #elif defined(_LIBUNWIND_TARGET_ARM) if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; #endif return false; } template unw_word_t UnwindCursor::getReg(int regNum) { switch (regNum) { #if defined(_LIBUNWIND_TARGET_X86_64) case UNW_REG_IP: return _msContext.Rip; case UNW_X86_64_RAX: return _msContext.Rax; case UNW_X86_64_RDX: return _msContext.Rdx; case UNW_X86_64_RCX: return _msContext.Rcx; case UNW_X86_64_RBX: return _msContext.Rbx; case UNW_REG_SP: case UNW_X86_64_RSP: return _msContext.Rsp; case UNW_X86_64_RBP: return _msContext.Rbp; case UNW_X86_64_RSI: return _msContext.Rsi; case UNW_X86_64_RDI: return _msContext.Rdi; case UNW_X86_64_R8: return _msContext.R8; case UNW_X86_64_R9: return _msContext.R9; case UNW_X86_64_R10: return _msContext.R10; case UNW_X86_64_R11: return _msContext.R11; case UNW_X86_64_R12: return _msContext.R12; case UNW_X86_64_R13: return _msContext.R13; case UNW_X86_64_R14: return _msContext.R14; case UNW_X86_64_R15: return _msContext.R15; #elif defined(_LIBUNWIND_TARGET_ARM) case UNW_ARM_R0: return _msContext.R0; case UNW_ARM_R1: return _msContext.R1; case UNW_ARM_R2: return _msContext.R2; case UNW_ARM_R3: return _msContext.R3; case UNW_ARM_R4: return _msContext.R4; case UNW_ARM_R5: return _msContext.R5; case UNW_ARM_R6: return _msContext.R6; case UNW_ARM_R7: return _msContext.R7; case UNW_ARM_R8: return _msContext.R8; case UNW_ARM_R9: return _msContext.R9; case UNW_ARM_R10: return _msContext.R10; case UNW_ARM_R11: return _msContext.R11; case UNW_ARM_R12: return _msContext.R12; case UNW_REG_SP: case UNW_ARM_SP: return _msContext.Sp; case UNW_ARM_LR: return _msContext.Lr; case UNW_REG_IP: case UNW_ARM_IP: return _msContext.Pc; #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: return _msContext.Sp; case UNW_REG_IP: return _msContext.Pc; default: return _msContext.X[regNum - UNW_ARM64_X0]; #endif } _LIBUNWIND_ABORT("unsupported register"); } template void UnwindCursor::setReg(int regNum, unw_word_t value) { switch (regNum) { #if defined(_LIBUNWIND_TARGET_X86_64) case UNW_REG_IP: _msContext.Rip = value; break; case UNW_X86_64_RAX: _msContext.Rax = value; break; case UNW_X86_64_RDX: _msContext.Rdx = value; break; case UNW_X86_64_RCX: _msContext.Rcx = value; break; case UNW_X86_64_RBX: _msContext.Rbx = value; break; case UNW_REG_SP: case UNW_X86_64_RSP: _msContext.Rsp = value; break; case UNW_X86_64_RBP: _msContext.Rbp = value; break; case UNW_X86_64_RSI: _msContext.Rsi = value; break; case UNW_X86_64_RDI: _msContext.Rdi = value; break; case UNW_X86_64_R8: _msContext.R8 = value; break; case UNW_X86_64_R9: _msContext.R9 = value; break; case UNW_X86_64_R10: _msContext.R10 = value; break; case UNW_X86_64_R11: _msContext.R11 = value; break; case UNW_X86_64_R12: _msContext.R12 = value; break; case UNW_X86_64_R13: _msContext.R13 = value; break; case UNW_X86_64_R14: _msContext.R14 = value; break; case UNW_X86_64_R15: _msContext.R15 = value; break; #elif defined(_LIBUNWIND_TARGET_ARM) case UNW_ARM_R0: _msContext.R0 = value; break; case UNW_ARM_R1: _msContext.R1 = value; break; case UNW_ARM_R2: _msContext.R2 = value; break; case UNW_ARM_R3: _msContext.R3 = value; break; case UNW_ARM_R4: _msContext.R4 = value; break; case UNW_ARM_R5: _msContext.R5 = value; break; case UNW_ARM_R6: _msContext.R6 = value; break; case UNW_ARM_R7: _msContext.R7 = value; break; case UNW_ARM_R8: _msContext.R8 = value; break; case UNW_ARM_R9: _msContext.R9 = value; break; case UNW_ARM_R10: _msContext.R10 = value; break; case UNW_ARM_R11: _msContext.R11 = value; break; case UNW_ARM_R12: _msContext.R12 = value; break; case UNW_REG_SP: case UNW_ARM_SP: _msContext.Sp = value; break; case UNW_ARM_LR: _msContext.Lr = value; break; case UNW_REG_IP: case UNW_ARM_IP: _msContext.Pc = value; break; #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: _msContext.Sp = value; break; case UNW_REG_IP: _msContext.Pc = value; break; case UNW_ARM64_X0: case UNW_ARM64_X1: case UNW_ARM64_X2: case UNW_ARM64_X3: case UNW_ARM64_X4: case UNW_ARM64_X5: case UNW_ARM64_X6: case UNW_ARM64_X7: case UNW_ARM64_X8: case UNW_ARM64_X9: case UNW_ARM64_X10: case UNW_ARM64_X11: case UNW_ARM64_X12: case UNW_ARM64_X13: case UNW_ARM64_X14: case UNW_ARM64_X15: case UNW_ARM64_X16: case UNW_ARM64_X17: case UNW_ARM64_X18: case UNW_ARM64_X19: case UNW_ARM64_X20: case UNW_ARM64_X21: case UNW_ARM64_X22: case UNW_ARM64_X23: case UNW_ARM64_X24: case UNW_ARM64_X25: case UNW_ARM64_X26: case UNW_ARM64_X27: case UNW_ARM64_X28: case UNW_ARM64_FP: case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; #endif default: _LIBUNWIND_ABORT("unsupported register"); } } template bool UnwindCursor::validFloatReg(int regNum) { #if defined(_LIBUNWIND_TARGET_ARM) if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; #else (void)regNum; #endif return false; } template unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { #if defined(_LIBUNWIND_TARGET_ARM) if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { union { uint32_t w; float f; } d; d.w = _msContext.S[regNum - UNW_ARM_S0]; return d.f; } if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { union { uint64_t w; double d; } d; d.w = _msContext.D[regNum - UNW_ARM_D0]; return d.d; } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) return _msContext.V[regNum - UNW_ARM64_D0].D[0]; #else (void)regNum; _LIBUNWIND_ABORT("float registers unimplemented"); #endif } template void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { #if defined(_LIBUNWIND_TARGET_ARM) if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { union { uint32_t w; float f; } d; d.f = value; _msContext.S[regNum - UNW_ARM_S0] = d.w; } if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { union { uint64_t w; double d; } d; d.d = value; _msContext.D[regNum - UNW_ARM_D0] = d.w; } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; #else (void)regNum; (void)value; _LIBUNWIND_ABORT("float registers unimplemented"); #endif } template void UnwindCursor::jumpto() { RtlRestoreContext(&_msContext, nullptr); } #ifdef __arm__ template void UnwindCursor::saveVFPAsX() {} #endif template const char *UnwindCursor::getRegisterName(int regNum) { return R::getRegisterName(regNum); } template bool UnwindCursor::isSignalFrame() { return false; } #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32) /// UnwindCursor contains all state (including all register values) during /// an unwind. This is normally stack allocated inside a unw_cursor_t. template class UnwindCursor : public AbstractUnwindCursor{ typedef typename A::pint_t pint_t; public: 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 bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); virtual int step(); virtual void getInfo(unw_proc_info_t *); virtual void jumpto(); virtual bool isSignalFrame(); virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); virtual const char *getRegisterName(int num); #ifdef __arm__ virtual void saveVFPAsX(); #endif // libunwind does not and should not depend on C++ library which means that we // need our own defition of inline placement new. static void *operator new(size_t, UnwindCursor *p) { return p; } private: #if defined(_LIBUNWIND_ARM_EHABI) bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); int stepWithEHABI() { size_t len = 0; size_t off = 0; // FIXME: Calling decode_eht_entry() here is violating the libunwind // abstraction layer. const uint32_t *ehtp = decode_eht_entry(reinterpret_cast(_info.unwind_info), &off, &len); if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) != _URC_CONTINUE_UNWIND) return UNW_STEP_END; return UNW_STEP_SUCCESS; } #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint=0); int stepWithDwarfFDE() { return DwarfInstructions::stepWithDwarf(_addressSpace, (pint_t)this->getReg(UNW_REG_IP), (pint_t)_info.unwind_info, _registers, _isSignalFrame); } #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) bool getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s); int stepWithCompactEncoding() { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) if ( compactSaysUseDwarf() ) return stepWithDwarfFDE(); #endif R dummy; return stepWithCompactEncoding(dummy); } #if defined(_LIBUNWIND_TARGET_X86_64) int stepWithCompactEncoding(Registers_x86_64 &) { return CompactUnwinder_x86_64::stepWithCompactEncoding( _info.format, _info.start_ip, _addressSpace, _registers); } #endif #if defined(_LIBUNWIND_TARGET_I386) int stepWithCompactEncoding(Registers_x86 &) { return CompactUnwinder_x86::stepWithCompactEncoding( _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers); } #endif #if defined(_LIBUNWIND_TARGET_PPC) int stepWithCompactEncoding(Registers_ppc &) { return UNW_EINVAL; } #endif #if defined(_LIBUNWIND_TARGET_PPC64) int stepWithCompactEncoding(Registers_ppc64 &) { return UNW_EINVAL; } #endif #if defined(_LIBUNWIND_TARGET_AARCH64) int stepWithCompactEncoding(Registers_arm64 &) { return CompactUnwinder_arm64::stepWithCompactEncoding( _info.format, _info.start_ip, _addressSpace, _registers); } #endif #if defined(_LIBUNWIND_TARGET_MIPS_O32) int stepWithCompactEncoding(Registers_mips_o32 &) { return UNW_EINVAL; } #endif #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) int stepWithCompactEncoding(Registers_mips_newabi &) { return UNW_EINVAL; } #endif #if defined(_LIBUNWIND_TARGET_SPARC) int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } #endif #if defined (_LIBUNWIND_TARGET_RISCV) int stepWithCompactEncoding(Registers_riscv &) { return UNW_EINVAL; } #endif bool compactSaysUseDwarf(uint32_t *offset=NULL) const { R dummy; return compactSaysUseDwarf(dummy, offset); } #if defined(_LIBUNWIND_TARGET_X86_64) bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { if (offset) *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); return true; } return false; } #endif #if defined(_LIBUNWIND_TARGET_I386) bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const { if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) { if (offset) *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET); return true; } return false; } #endif #if defined(_LIBUNWIND_TARGET_PPC) bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { return true; } #endif #if defined(_LIBUNWIND_TARGET_PPC64) bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { return true; } #endif #if defined(_LIBUNWIND_TARGET_AARCH64) bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { if (offset) *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET); return true; } return false; } #endif #if defined(_LIBUNWIND_TARGET_MIPS_O32) bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { return true; } #endif #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { return true; } #endif #if defined(_LIBUNWIND_TARGET_SPARC) bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } #endif #if defined (_LIBUNWIND_TARGET_RISCV) bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const { return true; } #endif #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) compact_unwind_encoding_t dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); } #if defined(_LIBUNWIND_TARGET_X86_64) compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { return UNWIND_X86_64_MODE_DWARF; } #endif #if defined(_LIBUNWIND_TARGET_I386) compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { return UNWIND_X86_MODE_DWARF; } #endif #if defined(_LIBUNWIND_TARGET_PPC) compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { return 0; } #endif #if defined(_LIBUNWIND_TARGET_PPC64) compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { return 0; } #endif #if defined(_LIBUNWIND_TARGET_AARCH64) compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { return UNWIND_ARM64_MODE_DWARF; } #endif #if defined(_LIBUNWIND_TARGET_ARM) compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { return 0; } #endif #if defined (_LIBUNWIND_TARGET_OR1K) compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { return 0; } #endif -#if defined (_LIBUNWIND_TARGET_RISCV) - compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { - return 0; - } -#endif - #if defined (_LIBUNWIND_TARGET_MIPS_O32) compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { return 0; } #endif #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { return 0; } #endif #if defined(_LIBUNWIND_TARGET_SPARC) compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } #endif #if defined (_LIBUNWIND_TARGET_RISCV) compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { return 0; } #endif #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) // For runtime environments using SEH unwind data without Windows runtime // support. pint_t getLastPC() const { /* FIXME: Implement */ return 0; } void setLastPC(pint_t pc) { /* FIXME: Implement */ } RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { /* FIXME: Implement */ *base = 0; return nullptr; } bool getInfoFromSEH(pint_t pc); int stepWithSEHData() { /* FIXME: Implement */ return 0; } #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) A &_addressSpace; R _registers; unw_proc_info_t _info; bool _unwindInfoMissing; bool _isSignalFrame; }; template UnwindCursor::UnwindCursor(unw_context_t *context, A &as) : _addressSpace(as), _registers(context), _unwindInfoMissing(false), _isSignalFrame(false) { static_assert((check_fit, unw_cursor_t>::does_fit), "UnwindCursor<> does not fit in unw_cursor_t"); memset(&_info, 0, sizeof(_info)); } template UnwindCursor::UnwindCursor(A &as, void *) : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { memset(&_info, 0, sizeof(_info)); // FIXME // fill in _registers from thread arg } template bool UnwindCursor::validReg(int regNum) { return _registers.validRegister(regNum); } template unw_word_t UnwindCursor::getReg(int regNum) { return _registers.getRegister(regNum); } template void UnwindCursor::setReg(int regNum, unw_word_t value) { _registers.setRegister(regNum, (typename A::pint_t)value); } template bool UnwindCursor::validFloatReg(int regNum) { return _registers.validFloatRegister(regNum); } template unw_fpreg_t UnwindCursor::getFloatReg(int regNum) { return _registers.getFloatRegister(regNum); } template void UnwindCursor::setFloatReg(int regNum, unw_fpreg_t value) { _registers.setFloatRegister(regNum, value); } template void UnwindCursor::jumpto() { _registers.jumpto(); } #ifdef __arm__ template void UnwindCursor::saveVFPAsX() { _registers.saveVFPAsX(); } #endif template const char *UnwindCursor::getRegisterName(int regNum) { return _registers.getRegisterName(regNum); } template bool UnwindCursor::isSignalFrame() { return _isSignalFrame; } #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) #if defined(_LIBUNWIND_ARM_EHABI) template struct EHABISectionIterator { typedef EHABISectionIterator _Self; typedef typename A::pint_t value_type; typedef typename A::pint_t* pointer; typedef typename A::pint_t& reference; typedef size_t size_type; typedef size_t difference_type; static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { return _Self(addressSpace, sects, 0); } static _Self end(A& addressSpace, const UnwindInfoSections& sects) { return _Self(addressSpace, sects, sects.arm_section_length / sizeof(EHABIIndexEntry)); } EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) : _i(i), _addressSpace(&addressSpace), _sects(§s) {} _Self& operator++() { ++_i; return *this; } _Self& operator+=(size_t a) { _i += a; return *this; } _Self& operator--() { assert(_i > 0); --_i; return *this; } _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } size_t operator-(const _Self& other) { return _i - other._i; } bool operator==(const _Self& other) const { assert(_addressSpace == other._addressSpace); assert(_sects == other._sects); return _i == other._i; } typename A::pint_t operator*() const { return functionAddress(); } typename A::pint_t functionAddress() const { typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( EHABIIndexEntry, _i, functionOffset); return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); } typename A::pint_t dataAddress() { typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( EHABIIndexEntry, _i, data); return indexAddr; } private: size_t _i; A* _addressSpace; const UnwindInfoSections* _sects; }; namespace { template EHABISectionIterator EHABISectionUpperBound( EHABISectionIterator first, EHABISectionIterator last, typename A::pint_t value) { size_t len = last - first; while (len > 0) { size_t l2 = len / 2; EHABISectionIterator m = first + l2; if (value < *m) { len = l2; } else { first = ++m; len -= l2 + 1; } } return first; } } template bool UnwindCursor::getInfoFromEHABISection( pint_t pc, const UnwindInfoSections §s) { EHABISectionIterator begin = EHABISectionIterator::begin(_addressSpace, sects); EHABISectionIterator end = EHABISectionIterator::end(_addressSpace, sects); if (begin == end) return false; EHABISectionIterator itNextPC = EHABISectionUpperBound(begin, end, pc); if (itNextPC == begin) return false; EHABISectionIterator itThisPC = itNextPC - 1; pint_t thisPC = itThisPC.functionAddress(); // If an exception is thrown from a function, corresponding to the last entry // in the table, we don't really know the function extent and have to choose a // value for nextPC. Choosing max() will allow the range check during trace to // succeed. pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress(); pint_t indexDataAddr = itThisPC.dataAddress(); if (indexDataAddr == 0) return false; uint32_t indexData = _addressSpace.get32(indexDataAddr); if (indexData == UNW_EXIDX_CANTUNWIND) return false; // If the high bit is set, the exception handling table entry is inline inside // the index table entry on the second word (aka |indexDataAddr|). Otherwise, // the table points at an offset in the exception handling table (section 5 EHABI). pint_t exceptionTableAddr; uint32_t exceptionTableData; bool isSingleWordEHT; if (indexData & 0x80000000) { exceptionTableAddr = indexDataAddr; // TODO(ajwong): Should this data be 0? exceptionTableData = indexData; isSingleWordEHT = true; } else { exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData); exceptionTableData = _addressSpace.get32(exceptionTableAddr); isSingleWordEHT = false; } // Now we know the 3 things: // exceptionTableAddr -- exception handler table entry. // exceptionTableData -- the data inside the first word of the eht entry. // isSingleWordEHT -- whether the entry is in the index. unw_word_t personalityRoutine = 0xbadf00d; bool scope32 = false; uintptr_t lsda; // If the high bit in the exception handling table entry is set, the entry is // in compact form (section 6.3 EHABI). if (exceptionTableData & 0x80000000) { // Grab the index of the personality routine from the compact form. uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; uint32_t extraWords = 0; switch (choice) { case 0: personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; extraWords = 0; scope32 = false; lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4); break; case 1: personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1; extraWords = (exceptionTableData & 0x00ff0000) >> 16; scope32 = false; lsda = exceptionTableAddr + (extraWords + 1) * 4; break; case 2: personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2; extraWords = (exceptionTableData & 0x00ff0000) >> 16; scope32 = true; lsda = exceptionTableAddr + (extraWords + 1) * 4; break; default: _LIBUNWIND_ABORT("unknown personality routine"); return false; } if (isSingleWordEHT) { if (extraWords != 0) { _LIBUNWIND_ABORT("index inlined table detected but pr function " "requires extra words"); return false; } } } else { pint_t personalityAddr = exceptionTableAddr + signExtendPrel31(exceptionTableData); personalityRoutine = personalityAddr; // ARM EHABI # 6.2, # 9.2 // // +---- ehtp // v // +--------------------------------------+ // | +--------+--------+--------+-------+ | // | |0| prel31 to personalityRoutine | | // | +--------+--------+--------+-------+ | // | | N | unwind opcodes | | <-- UnwindData // | +--------+--------+--------+-------+ | // | | Word 2 unwind opcodes | | // | +--------+--------+--------+-------+ | // | ... | // | +--------+--------+--------+-------+ | // | | Word N unwind opcodes | | // | +--------+--------+--------+-------+ | // | | LSDA | | <-- lsda // | | ... | | // | +--------+--------+--------+-------+ | // +--------------------------------------+ uint32_t *UnwindData = reinterpret_cast(exceptionTableAddr) + 1; uint32_t FirstDataWord = *UnwindData; size_t N = ((FirstDataWord >> 24) & 0xff); size_t NDataWords = N + 1; lsda = reinterpret_cast(UnwindData + NDataWords); } _info.start_ip = thisPC; _info.end_ip = nextPC; _info.handler = personalityRoutine; _info.unwind_info = exceptionTableAddr; _info.lsda = lsda; // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? return true; } #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) template bool UnwindCursor::getInfoFromDwarfSection(pint_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, (uint32_t)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( _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); if (cachedFDE != 0) { foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, (uint32_t)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, (uint32_t)sects.dwarf_section_length, 0, &fdeInfo, &cieInfo); } if (foundFDE) { typename CFI_Parser::PrologInfo prolog; if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // Save off parsed FDE info _info.start_ip = fdeInfo.pcStart; _info.end_ip = fdeInfo.pcEnd; _info.lsda = fdeInfo.lsda; _info.handler = cieInfo.personality; _info.gp = prolog.spExtraArgSize; _info.flags = 0; _info.format = dwarfEncoding(); _info.unwind_info = fdeInfo.fdeStart; _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; _info.extra = (unw_word_t) sects.dso_base; // Add to cache (to make next lookup faster) if we had no hint // and there was no index. if (!foundInCache && (fdeSectionOffsetHint == 0)) { #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (sects.dwarf_index_section == 0) #endif DwarfFDECache::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart); } return true; } } //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); return false; } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) template bool UnwindCursor::getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s) { const bool log = false; if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", (uint64_t)pc, (uint64_t)sects.dso_base); const UnwindSectionHeader sectionHeader(_addressSpace, sects.compact_unwind_section); if (sectionHeader.version() != UNWIND_SECTION_VERSION) return false; // do a binary search of top level index to find page with unwind info pint_t targetFunctionOffset = pc - sects.dso_base; const UnwindSectionIndexArray topIndex(_addressSpace, sects.compact_unwind_section + sectionHeader.indexSectionOffset()); uint32_t low = 0; uint32_t high = sectionHeader.indexCount(); uint32_t last = high - 1; while (low < high) { uint32_t mid = (low + high) / 2; //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", //mid, low, high, topIndex.functionOffset(mid)); if (topIndex.functionOffset(mid) <= targetFunctionOffset) { if ((mid == last) || (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { low = mid; break; } else { low = mid + 1; } } else { high = mid; } } const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); const uint32_t firstLevelNextPageFunctionOffset = topIndex.functionOffset(low + 1); const pint_t secondLevelAddr = sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low); const pint_t lsdaArrayStartAddr = sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low); const pint_t lsdaArrayEndAddr = sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1); if (log) fprintf(stderr, "\tfirst level search for result index=%d " "to secondLevelAddr=0x%llX\n", low, (uint64_t) secondLevelAddr); // do a binary search of second level page index uint32_t encoding = 0; pint_t funcStart = 0; pint_t funcEnd = 0; pint_t lsda = 0; pint_t personality = 0; uint32_t pageKind = _addressSpace.get32(secondLevelAddr); if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) { // regular page UnwindSectionRegularPageHeader pageHeader(_addressSpace, secondLevelAddr); UnwindSectionRegularArray pageIndex( _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); // binary search looks for entry with e where index[e].offset <= pc < // index[e+1].offset if (log) fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in " "regular page starting at secondLevelAddr=0x%llX\n", (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr); low = 0; high = pageHeader.entryCount(); while (low < high) { uint32_t mid = (low + high) / 2; if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { // at end of table low = mid; funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; break; } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { // next is too big, so we found it low = mid; funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base; break; } else { low = mid + 1; } } else { high = mid; } } encoding = pageIndex.encoding(low); funcStart = pageIndex.functionOffset(low) + sects.dso_base; if (pc < funcStart) { if (log) fprintf( stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); return false; } if (pc > funcEnd) { if (log) fprintf( stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); return false; } } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { // compressed page UnwindSectionCompressedPageHeader pageHeader(_addressSpace, secondLevelAddr); UnwindSectionCompressedArray pageIndex( _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); const uint32_t targetFunctionPageOffset = (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); // binary search looks for entry with e where index[e].offset <= pc < // index[e+1].offset if (log) fprintf(stderr, "\tbinary search of compressed page starting at " "secondLevelAddr=0x%llX\n", (uint64_t) secondLevelAddr); low = 0; last = pageHeader.entryCount() - 1; high = pageHeader.entryCount(); while (low < high) { uint32_t mid = (low + high) / 2; if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { if ((mid == last) || (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { low = mid; break; } else { low = mid + 1; } } else { high = mid; } } funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + sects.dso_base; if (low < last) funcEnd = pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset + sects.dso_base; else funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; if (pc < funcStart) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " "level compressed unwind table. funcStart=0x%llX", (uint64_t) pc, (uint64_t) funcStart); return false; } if (pc > funcEnd) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " "level compressed unwind table. funcEnd=0x%llX", (uint64_t) pc, (uint64_t) funcEnd); return false; } uint16_t encodingIndex = pageIndex.encodingIndex(low); if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { // encoding is in common table in section header encoding = _addressSpace.get32( sects.compact_unwind_section + sectionHeader.commonEncodingsArraySectionOffset() + encodingIndex * sizeof(uint32_t)); } else { // encoding is in page specific table uint16_t pageEncodingIndex = encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); encoding = _addressSpace.get32(secondLevelAddr + pageHeader.encodingsPageOffset() + pageEncodingIndex * sizeof(uint32_t)); } } else { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " "level page", (uint64_t) sects.compact_unwind_section); return false; } // look up LSDA, if encoding says function has one if (encoding & UNWIND_HAS_LSDA) { UnwindSectionLsdaArray lsdaIndex(_addressSpace, lsdaArrayStartAddr); uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); low = 0; high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / sizeof(unwind_info_section_header_lsda_index_entry); // binary search looks for entry with exact match for functionOffset if (log) fprintf(stderr, "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", funcStartOffset); while (low < high) { uint32_t mid = (low + high) / 2; if (lsdaIndex.functionOffset(mid) == funcStartOffset) { lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; break; } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { low = mid + 1; } else { high = mid; } } if (lsda == 0) { _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " "pc=0x%0llX, but lsda table has no entry", encoding, (uint64_t) pc); return false; } } // extact personality routine, if encoding says function has one uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> (__builtin_ctz(UNWIND_PERSONALITY_MASK)); if (personalityIndex != 0) { --personalityIndex; // change 1-based to zero-based index if (personalityIndex > sectionHeader.personalityArrayCount()) { _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " "but personality table has only %d entries", encoding, personalityIndex, sectionHeader.personalityArrayCount()); return false; } int32_t personalityDelta = (int32_t)_addressSpace.get32( sects.compact_unwind_section + sectionHeader.personalityArraySectionOffset() + personalityIndex * sizeof(uint32_t)); pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; personality = _addressSpace.getP(personalityPointer); if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " "personalityDelta=0x%08X, personality=0x%08llX\n", (uint64_t) pc, personalityDelta, (uint64_t) personality); } if (log) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); _info.start_ip = funcStart; _info.end_ip = funcEnd; _info.lsda = lsda; _info.handler = personality; _info.gp = 0; _info.flags = 0; _info.format = encoding; _info.unwind_info = 0; _info.unwind_info_size = 0; _info.extra = sects.dso_base; return true; } #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) template bool UnwindCursor::getInfoFromSEH(pint_t pc) { pint_t base; RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base); if (!unwindEntry) { _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc); return false; } _info.gp = 0; _info.flags = 0; _info.format = 0; _info.unwind_info_size = sizeof(RUNTIME_FUNCTION); _info.unwind_info = reinterpret_cast(unwindEntry); _info.extra = base; _info.start_ip = base + unwindEntry->BeginAddress; #ifdef _LIBUNWIND_TARGET_X86_64 _info.end_ip = base + unwindEntry->EndAddress; // Only fill in the handler and LSDA if they're stale. if (pc != getLastPC()) { UNWIND_INFO *xdata = reinterpret_cast(base + unwindEntry->UnwindData); if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) { // The personality is given in the UNWIND_INFO itself. The LSDA immediately // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit // these structures.) // N.B. UNWIND_INFO structs are DWORD-aligned. uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; const uint32_t *handler = reinterpret_cast(&xdata->UnwindCodes[lastcode]); _info.lsda = reinterpret_cast(handler+1); if (*handler) { _info.handler = reinterpret_cast(__libunwind_seh_personality); } else _info.handler = 0; } else { _info.lsda = 0; _info.handler = 0; } } #elif defined(_LIBUNWIND_TARGET_ARM) _info.end_ip = _info.start_ip + unwindEntry->FunctionLength; _info.lsda = 0; // FIXME _info.handler = 0; // FIXME #endif setLastPC(pc); return true; } #endif template void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { pint_t pc = (pint_t)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; #endif // If the last line of a function is a "throw" the compiler sometimes // emits no instructions after the call to __cxa_throw. This means // the return address is actually the start of the next function. // To disambiguate this, back up the pc when we know it is a return // address. if (isReturnAddress) --pc; // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; if (_addressSpace.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) { if (this->getInfoFromCompactEncodingSection(pc, sects)) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // Found info in table, done unless encoding says to use dwarf. uint32_t dwarfOffset; if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { // found info in dwarf, done return; } } #endif // If unwind table has entry, but entry says there is no unwind info, // record that we have no unwind info. if (_info.format == 0) _unwindInfoMissing = true; return; } } #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) // If there is SEH unwind info, look there next. if (this->getInfoFromSEH(pc)) return; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // If there is dwarf unwind info, look there next. if (sects.dwarf_section != 0) { if (this->getInfoFromDwarfSection(pc, sects)) { // found info in dwarf, done return; } } #endif #if defined(_LIBUNWIND_ARM_EHABI) // If there is ARM EHABI unwind info, look there next. if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) return; #endif } #if 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(0, pc); if (cachedFDE != 0) { CFI_Parser::FDE_Info fdeInfo; CFI_Parser::CIE_Info cieInfo; const char *msg = CFI_Parser::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo); if (msg == NULL) { typename CFI_Parser::PrologInfo prolog; if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // save off parsed FDE info _info.start_ip = fdeInfo.pcStart; _info.end_ip = fdeInfo.pcEnd; _info.lsda = fdeInfo.lsda; _info.handler = cieInfo.personality; _info.gp = prolog.spExtraArgSize; // Some frameless functions need SP // altered when resuming in function. _info.flags = 0; _info.format = dwarfEncoding(); _info.unwind_info = fdeInfo.fdeStart; _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; _info.extra = 0; return; } } } // Lastly, ask AddressSpace object about platform specific ways to locate // other FDEs. pint_t fde; if (_addressSpace.findOtherFDE(pc, fde)) { CFI_Parser::FDE_Info fdeInfo; CFI_Parser::CIE_Info cieInfo; if (!CFI_Parser::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { // Double check this FDE is for a function that includes the pc. if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { typename CFI_Parser::PrologInfo prolog; if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { // save off parsed FDE info _info.start_ip = fdeInfo.pcStart; _info.end_ip = fdeInfo.pcEnd; _info.lsda = fdeInfo.lsda; _info.handler = cieInfo.personality; _info.gp = prolog.spExtraArgSize; _info.flags = 0; _info.format = dwarfEncoding(); _info.unwind_info = fdeInfo.fdeStart; _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; _info.extra = 0; return; } } } } #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // no unwind info, flag that we can't reliably unwind _unwindInfoMissing = true; } template int UnwindCursor::step() { // Bottom of stack is defined is when unwind info cannot be found. if (_unwindInfoMissing) return UNW_STEP_END; // Use unwinding info to modify register set as if function returned. int result; #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) result = this->stepWithCompactEncoding(); #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) result = this->stepWithSEHData(); #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) result = this->stepWithDwarfFDE(); #elif defined(_LIBUNWIND_ARM_EHABI) result = this->stepWithEHABI(); #else #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ _LIBUNWIND_SUPPORT_SEH_UNWIND or \ _LIBUNWIND_SUPPORT_DWARF_UNWIND or \ _LIBUNWIND_ARM_EHABI #endif // update info based on new PC if (result == UNW_STEP_SUCCESS) { this->setInfoBasedOnIPRegister(true); if (_unwindInfoMissing) return UNW_STEP_END; } return result; } template void UnwindCursor::getInfo(unw_proc_info_t *info) { if (_unwindInfoMissing) memset(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); } } // namespace libunwind #endif // __UNWINDCURSOR_HPP__ Index: projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersRestore.S =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersRestore.S (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersRestore.S (revision 357209) @@ -1,1199 +1,1118 @@ //===-------------------- UnwindRegistersRestore.S ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "assembly.h" .text #if !defined(__USING_SJLJ_EXCEPTIONS__) #if defined(__i386__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) # # void libunwind::Registers_x86::jumpto() # #if defined(_WIN32) # On windows, the 'this' pointer is passed in ecx instead of on the stack movl %ecx, %eax #else # On entry: # + + # +-----------------------+ # + thread_state pointer + # +-----------------------+ # + return address + # +-----------------------+ <-- SP # + + movl 4(%esp), %eax #endif # set up eax and ret on new stack location movl 28(%eax), %edx # edx holds new stack pointer subl $8,%edx movl %edx, 28(%eax) movl 0(%eax), %ebx movl %ebx, 0(%edx) movl 40(%eax), %ebx movl %ebx, 4(%edx) # we now have ret and eax pushed onto where new stack will be # restore all registers movl 4(%eax), %ebx movl 8(%eax), %ecx movl 12(%eax), %edx movl 16(%eax), %edi movl 20(%eax), %esi movl 24(%eax), %ebp movl 28(%eax), %esp # skip ss # skip eflags pop %eax # eax was already pushed on new stack ret # eip was already pushed on new stack # skip cs # skip ds # skip es # skip fs # skip gs #elif defined(__x86_64__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) # # void libunwind::Registers_x86_64::jumpto() # #if defined(_WIN64) # On entry, thread_state pointer is in rcx; move it into rdi # to share restore code below. Since this routine restores and # overwrites all registers, we can use the same registers for # pointers and temporaries as on unix even though win64 normally # mustn't clobber some of them. movq %rcx, %rdi #else # On entry, thread_state pointer is in rdi #endif movq 56(%rdi), %rax # rax holds new stack pointer subq $16, %rax movq %rax, 56(%rdi) movq 32(%rdi), %rbx # store new rdi on new stack movq %rbx, 0(%rax) movq 128(%rdi), %rbx # store new rip on new stack movq %rbx, 8(%rax) # restore all registers movq 0(%rdi), %rax movq 8(%rdi), %rbx movq 16(%rdi), %rcx movq 24(%rdi), %rdx # restore rdi later movq 40(%rdi), %rsi movq 48(%rdi), %rbp # restore rsp later movq 64(%rdi), %r8 movq 72(%rdi), %r9 movq 80(%rdi), %r10 movq 88(%rdi), %r11 movq 96(%rdi), %r12 movq 104(%rdi), %r13 movq 112(%rdi), %r14 movq 120(%rdi), %r15 # skip rflags # skip cs # skip fs # skip gs #if defined(_WIN64) movdqu 176(%rdi),%xmm0 movdqu 192(%rdi),%xmm1 movdqu 208(%rdi),%xmm2 movdqu 224(%rdi),%xmm3 movdqu 240(%rdi),%xmm4 movdqu 256(%rdi),%xmm5 movdqu 272(%rdi),%xmm6 movdqu 288(%rdi),%xmm7 movdqu 304(%rdi),%xmm8 movdqu 320(%rdi),%xmm9 movdqu 336(%rdi),%xmm10 movdqu 352(%rdi),%xmm11 movdqu 368(%rdi),%xmm12 movdqu 384(%rdi),%xmm13 movdqu 400(%rdi),%xmm14 movdqu 416(%rdi),%xmm15 #endif movq 56(%rdi), %rsp # cut back rsp to new location pop %rdi # rdi was saved here earlier ret # rip was saved here #elif defined(__powerpc64__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) // // void libunwind::Registers_ppc64::jumpto() // // On entry: // thread_state pointer is in r3 // // load register (GPR) #define PPC64_LR(n) \ ld %r##n, (8 * (n + 2))(%r3) // restore integral registers // skip r0 for now // skip r1 for now PPC64_LR(2) // skip r3 for now // skip r4 for now // skip r5 for now PPC64_LR(6) PPC64_LR(7) PPC64_LR(8) PPC64_LR(9) PPC64_LR(10) PPC64_LR(11) PPC64_LR(12) PPC64_LR(13) PPC64_LR(14) PPC64_LR(15) PPC64_LR(16) PPC64_LR(17) PPC64_LR(18) PPC64_LR(19) PPC64_LR(20) PPC64_LR(21) PPC64_LR(22) PPC64_LR(23) PPC64_LR(24) PPC64_LR(25) PPC64_LR(26) PPC64_LR(27) PPC64_LR(28) PPC64_LR(29) PPC64_LR(30) PPC64_LR(31) #ifdef PPC64_HAS_VMX // restore VS registers // (note that this also restores floating point registers and V registers, // because part of VS is mapped to these registers) addi %r4, %r3, PPC64_OFFS_FP // load VS register #define PPC64_LVS(n) \ lxvd2x %vs##n, 0, %r4 ;\ addi %r4, %r4, 16 // restore the first 32 VS regs (and also all floating point regs) PPC64_LVS(0) PPC64_LVS(1) PPC64_LVS(2) PPC64_LVS(3) PPC64_LVS(4) PPC64_LVS(5) PPC64_LVS(6) PPC64_LVS(7) PPC64_LVS(8) PPC64_LVS(9) PPC64_LVS(10) PPC64_LVS(11) PPC64_LVS(12) PPC64_LVS(13) PPC64_LVS(14) PPC64_LVS(15) PPC64_LVS(16) PPC64_LVS(17) PPC64_LVS(18) PPC64_LVS(19) PPC64_LVS(20) PPC64_LVS(21) PPC64_LVS(22) PPC64_LVS(23) PPC64_LVS(24) PPC64_LVS(25) PPC64_LVS(26) PPC64_LVS(27) PPC64_LVS(28) PPC64_LVS(29) PPC64_LVS(30) PPC64_LVS(31) // use VRSAVE to conditionally restore the remaining VS regs, // that are where the V regs are mapped ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave cmpwi %r5, 0 beq Lnovec // conditionally load VS #define PPC64_CLVS_BOTTOM(n) \ beq Ldone##n ;\ addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ lxvd2x %vs##n, 0, %r4 ;\ Ldone##n: #define PPC64_CLVSl(n) \ andis. %r0, %r5, (1<<(47-n)) ;\ PPC64_CLVS_BOTTOM(n) #define PPC64_CLVSh(n) \ andi. %r0, %r5, (1<<(63-n)) ;\ PPC64_CLVS_BOTTOM(n) PPC64_CLVSl(32) PPC64_CLVSl(33) PPC64_CLVSl(34) PPC64_CLVSl(35) PPC64_CLVSl(36) PPC64_CLVSl(37) PPC64_CLVSl(38) PPC64_CLVSl(39) PPC64_CLVSl(40) PPC64_CLVSl(41) PPC64_CLVSl(42) PPC64_CLVSl(43) PPC64_CLVSl(44) PPC64_CLVSl(45) PPC64_CLVSl(46) PPC64_CLVSl(47) PPC64_CLVSh(48) PPC64_CLVSh(49) PPC64_CLVSh(50) PPC64_CLVSh(51) PPC64_CLVSh(52) PPC64_CLVSh(53) PPC64_CLVSh(54) PPC64_CLVSh(55) PPC64_CLVSh(56) PPC64_CLVSh(57) PPC64_CLVSh(58) PPC64_CLVSh(59) PPC64_CLVSh(60) PPC64_CLVSh(61) PPC64_CLVSh(62) PPC64_CLVSh(63) #else // load FP register #define PPC64_LF(n) \ lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) // restore float registers PPC64_LF(0) PPC64_LF(1) PPC64_LF(2) PPC64_LF(3) PPC64_LF(4) PPC64_LF(5) PPC64_LF(6) PPC64_LF(7) PPC64_LF(8) PPC64_LF(9) PPC64_LF(10) PPC64_LF(11) PPC64_LF(12) PPC64_LF(13) PPC64_LF(14) PPC64_LF(15) PPC64_LF(16) PPC64_LF(17) PPC64_LF(18) PPC64_LF(19) PPC64_LF(20) PPC64_LF(21) PPC64_LF(22) PPC64_LF(23) PPC64_LF(24) PPC64_LF(25) PPC64_LF(26) PPC64_LF(27) PPC64_LF(28) PPC64_LF(29) PPC64_LF(30) PPC64_LF(31) // restore vector registers if any are in use ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave cmpwi %r5, 0 beq Lnovec subi %r4, %r1, 16 // r4 is now a 16-byte aligned pointer into the red zone // the _vectorScalarRegisters may not be 16-byte aligned // so copy via red zone temp buffer #define PPC64_CLV_UNALIGNED_BOTTOM(n) \ beq Ldone##n ;\ ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ std %r0, 0(%r4) ;\ ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ std %r0, 8(%r4) ;\ lvx %v##n, 0, %r4 ;\ Ldone ## n: #define PPC64_CLV_UNALIGNEDl(n) \ andis. %r0, %r5, (1<<(15-n)) ;\ PPC64_CLV_UNALIGNED_BOTTOM(n) #define PPC64_CLV_UNALIGNEDh(n) \ andi. %r0, %r5, (1<<(31-n)) ;\ PPC64_CLV_UNALIGNED_BOTTOM(n) PPC64_CLV_UNALIGNEDl(0) PPC64_CLV_UNALIGNEDl(1) PPC64_CLV_UNALIGNEDl(2) PPC64_CLV_UNALIGNEDl(3) PPC64_CLV_UNALIGNEDl(4) PPC64_CLV_UNALIGNEDl(5) PPC64_CLV_UNALIGNEDl(6) PPC64_CLV_UNALIGNEDl(7) PPC64_CLV_UNALIGNEDl(8) PPC64_CLV_UNALIGNEDl(9) PPC64_CLV_UNALIGNEDl(10) PPC64_CLV_UNALIGNEDl(11) PPC64_CLV_UNALIGNEDl(12) PPC64_CLV_UNALIGNEDl(13) PPC64_CLV_UNALIGNEDl(14) PPC64_CLV_UNALIGNEDl(15) PPC64_CLV_UNALIGNEDh(16) PPC64_CLV_UNALIGNEDh(17) PPC64_CLV_UNALIGNEDh(18) PPC64_CLV_UNALIGNEDh(19) PPC64_CLV_UNALIGNEDh(20) PPC64_CLV_UNALIGNEDh(21) PPC64_CLV_UNALIGNEDh(22) PPC64_CLV_UNALIGNEDh(23) PPC64_CLV_UNALIGNEDh(24) PPC64_CLV_UNALIGNEDh(25) PPC64_CLV_UNALIGNEDh(26) PPC64_CLV_UNALIGNEDh(27) PPC64_CLV_UNALIGNEDh(28) PPC64_CLV_UNALIGNEDh(29) PPC64_CLV_UNALIGNEDh(30) PPC64_CLV_UNALIGNEDh(31) #endif Lnovec: ld %r0, PPC64_OFFS_CR(%r3) mtcr %r0 ld %r0, PPC64_OFFS_SRR0(%r3) mtctr %r0 PPC64_LR(0) PPC64_LR(5) PPC64_LR(4) PPC64_LR(1) PPC64_LR(3) bctr #elif defined(__ppc__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) // // void libunwind::Registers_ppc::jumpto() // // On entry: // thread_state pointer is in r3 // // restore integral registerrs // skip r0 for now // skip r1 for now lwz %r2, 16(%r3) // skip r3 for now // skip r4 for now // skip r5 for now lwz %r6, 32(%r3) lwz %r7, 36(%r3) lwz %r8, 40(%r3) lwz %r9, 44(%r3) lwz %r10, 48(%r3) lwz %r11, 52(%r3) lwz %r12, 56(%r3) lwz %r13, 60(%r3) lwz %r14, 64(%r3) lwz %r15, 68(%r3) lwz %r16, 72(%r3) lwz %r17, 76(%r3) lwz %r18, 80(%r3) lwz %r19, 84(%r3) lwz %r20, 88(%r3) lwz %r21, 92(%r3) lwz %r22, 96(%r3) lwz %r23,100(%r3) lwz %r24,104(%r3) lwz %r25,108(%r3) lwz %r26,112(%r3) lwz %r27,116(%r3) lwz %r28,120(%r3) lwz %r29,124(%r3) lwz %r30,128(%r3) lwz %r31,132(%r3) // restore float registers lfd %f0, 160(%r3) lfd %f1, 168(%r3) lfd %f2, 176(%r3) lfd %f3, 184(%r3) lfd %f4, 192(%r3) lfd %f5, 200(%r3) lfd %f6, 208(%r3) lfd %f7, 216(%r3) lfd %f8, 224(%r3) lfd %f9, 232(%r3) lfd %f10,240(%r3) lfd %f11,248(%r3) lfd %f12,256(%r3) lfd %f13,264(%r3) lfd %f14,272(%r3) lfd %f15,280(%r3) lfd %f16,288(%r3) lfd %f17,296(%r3) lfd %f18,304(%r3) lfd %f19,312(%r3) lfd %f20,320(%r3) lfd %f21,328(%r3) lfd %f22,336(%r3) lfd %f23,344(%r3) lfd %f24,352(%r3) lfd %f25,360(%r3) lfd %f26,368(%r3) lfd %f27,376(%r3) lfd %f28,384(%r3) lfd %f29,392(%r3) lfd %f30,400(%r3) lfd %f31,408(%r3) // restore vector registers if any are in use lwz %r5, 156(%r3) // test VRsave cmpwi %r5, 0 beq Lnovec subi %r4, %r1, 16 rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits // r4 is now a 16-byte aligned pointer into the red zone // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer #define LOAD_VECTOR_UNALIGNEDl(_index) \ andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \ beq Ldone ## _index SEPARATOR \ lwz %r0, 424+_index*16(%r3) SEPARATOR \ stw %r0, 0(%r4) SEPARATOR \ lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ stw %r0, 4(%r4) SEPARATOR \ lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ stw %r0, 8(%r4) SEPARATOR \ lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ stw %r0, 12(%r4) SEPARATOR \ lvx %v ## _index, 0, %r4 SEPARATOR \ Ldone ## _index: #define LOAD_VECTOR_UNALIGNEDh(_index) \ andi. %r0, %r5, (1<<(31-_index)) SEPARATOR \ beq Ldone ## _index SEPARATOR \ lwz %r0, 424+_index*16(%r3) SEPARATOR \ stw %r0, 0(%r4) SEPARATOR \ lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ stw %r0, 4(%r4) SEPARATOR \ lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ stw %r0, 8(%r4) SEPARATOR \ lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ stw %r0, 12(%r4) SEPARATOR \ lvx %v ## _index, 0, %r4 SEPARATOR \ Ldone ## _index: LOAD_VECTOR_UNALIGNEDl(0) LOAD_VECTOR_UNALIGNEDl(1) LOAD_VECTOR_UNALIGNEDl(2) LOAD_VECTOR_UNALIGNEDl(3) LOAD_VECTOR_UNALIGNEDl(4) LOAD_VECTOR_UNALIGNEDl(5) LOAD_VECTOR_UNALIGNEDl(6) LOAD_VECTOR_UNALIGNEDl(7) LOAD_VECTOR_UNALIGNEDl(8) LOAD_VECTOR_UNALIGNEDl(9) LOAD_VECTOR_UNALIGNEDl(10) LOAD_VECTOR_UNALIGNEDl(11) LOAD_VECTOR_UNALIGNEDl(12) LOAD_VECTOR_UNALIGNEDl(13) LOAD_VECTOR_UNALIGNEDl(14) LOAD_VECTOR_UNALIGNEDl(15) LOAD_VECTOR_UNALIGNEDh(16) LOAD_VECTOR_UNALIGNEDh(17) LOAD_VECTOR_UNALIGNEDh(18) LOAD_VECTOR_UNALIGNEDh(19) LOAD_VECTOR_UNALIGNEDh(20) LOAD_VECTOR_UNALIGNEDh(21) LOAD_VECTOR_UNALIGNEDh(22) LOAD_VECTOR_UNALIGNEDh(23) LOAD_VECTOR_UNALIGNEDh(24) LOAD_VECTOR_UNALIGNEDh(25) LOAD_VECTOR_UNALIGNEDh(26) LOAD_VECTOR_UNALIGNEDh(27) LOAD_VECTOR_UNALIGNEDh(28) LOAD_VECTOR_UNALIGNEDh(29) LOAD_VECTOR_UNALIGNEDh(30) LOAD_VECTOR_UNALIGNEDh(31) Lnovec: lwz %r0, 136(%r3) // __cr mtcr %r0 lwz %r0, 148(%r3) // __ctr mtctr %r0 lwz %r0, 0(%r3) // __ssr0 mtctr %r0 lwz %r0, 8(%r3) // do r0 now lwz %r5, 28(%r3) // do r5 now lwz %r4, 24(%r3) // do r4 now lwz %r1, 12(%r3) // do sp now lwz %r3, 20(%r3) // do r3 last bctr #elif defined(__arm64__) || defined(__aarch64__) // // void libunwind::Registers_arm64::jumpto() // // On entry: // thread_state pointer is in x0 // .p2align 2 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) // skip restore of x0,x1 for now ldp x2, x3, [x0, #0x010] ldp x4, x5, [x0, #0x020] ldp x6, x7, [x0, #0x030] ldp x8, x9, [x0, #0x040] ldp x10,x11, [x0, #0x050] ldp x12,x13, [x0, #0x060] ldp x14,x15, [x0, #0x070] // x16 and x17 were clobbered by the call into the unwinder, so no point in // restoring them. ldp x18,x19, [x0, #0x090] ldp x20,x21, [x0, #0x0A0] ldp x22,x23, [x0, #0x0B0] ldp x24,x25, [x0, #0x0C0] ldp x26,x27, [x0, #0x0D0] ldp x28,x29, [x0, #0x0E0] ldr x30, [x0, #0x100] // restore pc into lr ldp d0, d1, [x0, #0x110] ldp d2, d3, [x0, #0x120] ldp d4, d5, [x0, #0x130] ldp d6, d7, [x0, #0x140] ldp d8, d9, [x0, #0x150] ldp d10,d11, [x0, #0x160] ldp d12,d13, [x0, #0x170] ldp d14,d15, [x0, #0x180] ldp d16,d17, [x0, #0x190] ldp d18,d19, [x0, #0x1A0] ldp d20,d21, [x0, #0x1B0] ldp d22,d23, [x0, #0x1C0] ldp d24,d25, [x0, #0x1D0] ldp d26,d27, [x0, #0x1E0] ldp d28,d29, [x0, #0x1F0] ldr d30, [x0, #0x200] ldr d31, [x0, #0x208] // Finally, restore sp. This must be done after the the last read from the // 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] ldp x0, x1, [x0, #0x000] // restore x0,x1 mov sp,x16 // restore sp ret x30 // jump to pc #elif defined(__arm__) && !defined(__APPLE__) #if !defined(__ARM_ARCH_ISA_ARM) #if (__ARM_ARCH_ISA_THUMB == 2) .syntax unified #endif .thumb #endif @ @ void libunwind::Registers_arm::restoreCoreAndJumpTo() @ @ On entry: @ thread_state pointer is in r0 @ .p2align 2 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 @ r8-r11: ldm into r1-r4, then mov to r8-r11 adds r0, #0x20 ldm r0!, {r1-r4} subs r0, #0x30 mov r8, r1 mov r9, r2 mov r10, r3 mov r11, r4 @ r12 does not need loading, it it the intra-procedure-call scratch register ldr r2, [r0, #0x34] ldr r3, [r0, #0x3c] mov sp, r2 mov lr, r3 @ restore pc into lr ldm r0, {r0-r7} #else @ Use lr as base so that r0 can be restored. mov lr, r0 @ 32bit thumb-2 restrictions for ldm: @ . the sp (r13) cannot be in the list @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction ldm lr, {r0-r12} ldr sp, [lr, #52] ldr lr, [lr, #60] @ restore pc into lr #endif JMP(lr) @ @ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3-d16 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @ want the compiler to generate instructions that access those) but this is @ only accessed if the personality routine needs these registers. Use of @ these registers implies they are, actually, available on the target, so @ it's ok to execute. @ So, generate the instruction using the corresponding coprocessor mnemonic. vldmia r0, {d0-d15} JMP(lr) @ @ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3-d16 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv) vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia JMP(lr) @ @ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv) vldmia r0, {d16-d31} JMP(lr) #if defined(__ARM_WMMX) @ @ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .arch armv5te #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv) ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 JMP(lr) @ @ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .arch armv5te #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 JMP(lr) #endif #elif defined(__or1k__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) # # void libunwind::Registers_or1k::jumpto() # # On entry: # thread_state pointer is in r3 # # restore integral registers l.lwz r0, 0(r3) l.lwz r1, 4(r3) l.lwz r2, 8(r3) # skip r3 for now l.lwz r4, 16(r3) l.lwz r5, 20(r3) l.lwz r6, 24(r3) l.lwz r7, 28(r3) l.lwz r8, 32(r3) # skip r9 l.lwz r10, 40(r3) l.lwz r11, 44(r3) l.lwz r12, 48(r3) l.lwz r13, 52(r3) l.lwz r14, 56(r3) l.lwz r15, 60(r3) l.lwz r16, 64(r3) l.lwz r17, 68(r3) l.lwz r18, 72(r3) l.lwz r19, 76(r3) l.lwz r20, 80(r3) l.lwz r21, 84(r3) l.lwz r22, 88(r3) l.lwz r23, 92(r3) l.lwz r24, 96(r3) l.lwz r25,100(r3) l.lwz r26,104(r3) l.lwz r27,108(r3) l.lwz r28,112(r3) l.lwz r29,116(r3) l.lwz r30,120(r3) l.lwz r31,124(r3) # at last, restore r3 l.lwz r3, 12(r3) # load new pc into ra l.lwz r9, 128(r3) # jump to pc l.jr r9 l.nop -#elif defined(__riscv) - -// -// void libunwind::Registers_riscv::jumpto() -// -// On entry: -// thread_state pointer is in a0 -// - .p2align 2 -DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) -#ifdef __riscv_float_abi_double - fld f0, (8 * 32 + 8 * 0)(a0) - fld f1, (8 * 32 + 8 * 1)(a0) - fld f2, (8 * 32 + 8 * 2)(a0) - fld f3, (8 * 32 + 8 * 3)(a0) - fld f4, (8 * 32 + 8 * 4)(a0) - fld f5, (8 * 32 + 8 * 5)(a0) - fld f6, (8 * 32 + 8 * 6)(a0) - fld f7, (8 * 32 + 8 * 7)(a0) - fld f8, (8 * 32 + 8 * 8)(a0) - fld f9, (8 * 32 + 8 * 9)(a0) - fld f10, (8 * 32 + 8 * 10)(a0) - fld f11, (8 * 32 + 8 * 11)(a0) - fld f12, (8 * 32 + 8 * 12)(a0) - fld f13, (8 * 32 + 8 * 13)(a0) - fld f14, (8 * 32 + 8 * 14)(a0) - fld f15, (8 * 32 + 8 * 15)(a0) - fld f16, (8 * 32 + 8 * 16)(a0) - fld f17, (8 * 32 + 8 * 17)(a0) - fld f18, (8 * 32 + 8 * 18)(a0) - fld f19, (8 * 32 + 8 * 19)(a0) - fld f20, (8 * 32 + 8 * 20)(a0) - fld f21, (8 * 32 + 8 * 21)(a0) - fld f22, (8 * 32 + 8 * 22)(a0) - fld f23, (8 * 32 + 8 * 23)(a0) - fld f24, (8 * 32 + 8 * 24)(a0) - fld f25, (8 * 32 + 8 * 25)(a0) - fld f26, (8 * 32 + 8 * 26)(a0) - fld f27, (8 * 32 + 8 * 27)(a0) - fld f28, (8 * 32 + 8 * 28)(a0) - fld f29, (8 * 32 + 8 * 29)(a0) - fld f30, (8 * 32 + 8 * 30)(a0) - fld f31, (8 * 32 + 8 * 31)(a0) -#endif - - // x0 is zero - ld x1, (8 * 1)(a0) - ld x2, (8 * 2)(a0) - ld x3, (8 * 3)(a0) - ld x4, (8 * 4)(a0) - ld x5, (8 * 5)(a0) - ld x6, (8 * 6)(a0) - ld x7, (8 * 7)(a0) - ld x8, (8 * 8)(a0) - ld x9, (8 * 9)(a0) - // skip a0 for now - ld x11, (8 * 11)(a0) - ld x12, (8 * 12)(a0) - ld x13, (8 * 13)(a0) - ld x14, (8 * 14)(a0) - ld x15, (8 * 15)(a0) - ld x16, (8 * 16)(a0) - ld x17, (8 * 17)(a0) - ld x18, (8 * 18)(a0) - ld x19, (8 * 19)(a0) - ld x20, (8 * 20)(a0) - ld x21, (8 * 21)(a0) - ld x22, (8 * 22)(a0) - ld x23, (8 * 23)(a0) - ld x24, (8 * 24)(a0) - ld x25, (8 * 25)(a0) - ld x26, (8 * 26)(a0) - ld x27, (8 * 27)(a0) - ld x28, (8 * 28)(a0) - ld x29, (8 * 29)(a0) - ld x30, (8 * 30)(a0) - ld x31, (8 * 31)(a0) - ld x10, (8 * 10)(a0) // restore a0 - - ret // jump to ra - #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 // // void libunwind::Registers_mips_o32::jumpto() // // On entry: // thread state pointer is in a0 ($4) // DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) .set push .set noat .set noreorder .set nomacro #ifdef __mips_hard_float #if __mips_fpr != 64 ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) ldc1 $f6, (4 * 36 + 8 * 6)($4) ldc1 $f8, (4 * 36 + 8 * 8)($4) ldc1 $f10, (4 * 36 + 8 * 10)($4) ldc1 $f12, (4 * 36 + 8 * 12)($4) ldc1 $f14, (4 * 36 + 8 * 14)($4) ldc1 $f16, (4 * 36 + 8 * 16)($4) ldc1 $f18, (4 * 36 + 8 * 18)($4) ldc1 $f20, (4 * 36 + 8 * 20)($4) ldc1 $f22, (4 * 36 + 8 * 22)($4) ldc1 $f24, (4 * 36 + 8 * 24)($4) ldc1 $f26, (4 * 36 + 8 * 26)($4) ldc1 $f28, (4 * 36 + 8 * 28)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) #else ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f3, (4 * 36 + 8 * 3)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) ldc1 $f5, (4 * 36 + 8 * 5)($4) ldc1 $f6, (4 * 36 + 8 * 6)($4) ldc1 $f7, (4 * 36 + 8 * 7)($4) ldc1 $f8, (4 * 36 + 8 * 8)($4) ldc1 $f9, (4 * 36 + 8 * 9)($4) ldc1 $f10, (4 * 36 + 8 * 10)($4) ldc1 $f11, (4 * 36 + 8 * 11)($4) ldc1 $f12, (4 * 36 + 8 * 12)($4) ldc1 $f13, (4 * 36 + 8 * 13)($4) ldc1 $f14, (4 * 36 + 8 * 14)($4) ldc1 $f15, (4 * 36 + 8 * 15)($4) ldc1 $f16, (4 * 36 + 8 * 16)($4) ldc1 $f17, (4 * 36 + 8 * 17)($4) ldc1 $f18, (4 * 36 + 8 * 18)($4) ldc1 $f19, (4 * 36 + 8 * 19)($4) ldc1 $f20, (4 * 36 + 8 * 20)($4) ldc1 $f21, (4 * 36 + 8 * 21)($4) ldc1 $f22, (4 * 36 + 8 * 22)($4) ldc1 $f23, (4 * 36 + 8 * 23)($4) ldc1 $f24, (4 * 36 + 8 * 24)($4) ldc1 $f25, (4 * 36 + 8 * 25)($4) ldc1 $f26, (4 * 36 + 8 * 26)($4) ldc1 $f27, (4 * 36 + 8 * 27)($4) ldc1 $f28, (4 * 36 + 8 * 28)($4) ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) #endif #endif // restore hi and lo lw $8, (4 * 33)($4) mthi $8 lw $8, (4 * 34)($4) mtlo $8 // r0 is zero lw $1, (4 * 1)($4) lw $2, (4 * 2)($4) lw $3, (4 * 3)($4) // skip a0 for now lw $5, (4 * 5)($4) lw $6, (4 * 6)($4) lw $7, (4 * 7)($4) lw $8, (4 * 8)($4) lw $9, (4 * 9)($4) lw $10, (4 * 10)($4) lw $11, (4 * 11)($4) lw $12, (4 * 12)($4) lw $13, (4 * 13)($4) lw $14, (4 * 14)($4) lw $15, (4 * 15)($4) lw $16, (4 * 16)($4) lw $17, (4 * 17)($4) lw $18, (4 * 18)($4) lw $19, (4 * 19)($4) lw $20, (4 * 20)($4) lw $21, (4 * 21)($4) lw $22, (4 * 22)($4) lw $23, (4 * 23)($4) lw $24, (4 * 24)($4) lw $25, (4 * 25)($4) lw $26, (4 * 26)($4) 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) // jump to ra, load a0 in the delay slot jr $31 lw $4, (4 * 4)($4) .set pop #elif defined(__mips64) // // void libunwind::Registers_mips_newabi::jumpto() // // On entry: // thread state pointer is in a0 ($4) // DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) .set push .set noat .set noreorder .set nomacro #ifdef __mips_hard_float ldc1 $f0, (8 * 35)($4) ldc1 $f1, (8 * 36)($4) ldc1 $f2, (8 * 37)($4) ldc1 $f3, (8 * 38)($4) ldc1 $f4, (8 * 39)($4) ldc1 $f5, (8 * 40)($4) ldc1 $f6, (8 * 41)($4) ldc1 $f7, (8 * 42)($4) ldc1 $f8, (8 * 43)($4) ldc1 $f9, (8 * 44)($4) ldc1 $f10, (8 * 45)($4) ldc1 $f11, (8 * 46)($4) ldc1 $f12, (8 * 47)($4) ldc1 $f13, (8 * 48)($4) ldc1 $f14, (8 * 49)($4) ldc1 $f15, (8 * 50)($4) ldc1 $f16, (8 * 51)($4) ldc1 $f17, (8 * 52)($4) ldc1 $f18, (8 * 53)($4) ldc1 $f19, (8 * 54)($4) ldc1 $f20, (8 * 55)($4) ldc1 $f21, (8 * 56)($4) ldc1 $f22, (8 * 57)($4) ldc1 $f23, (8 * 58)($4) ldc1 $f24, (8 * 59)($4) ldc1 $f25, (8 * 60)($4) ldc1 $f26, (8 * 61)($4) ldc1 $f27, (8 * 62)($4) ldc1 $f28, (8 * 63)($4) ldc1 $f29, (8 * 64)($4) ldc1 $f30, (8 * 65)($4) ldc1 $f31, (8 * 66)($4) #endif // restore hi and lo ld $8, (8 * 33)($4) mthi $8 ld $8, (8 * 34)($4) mtlo $8 // r0 is zero ld $1, (8 * 1)($4) ld $2, (8 * 2)($4) ld $3, (8 * 3)($4) // skip a0 for now ld $5, (8 * 5)($4) ld $6, (8 * 6)($4) ld $7, (8 * 7)($4) ld $8, (8 * 8)($4) ld $9, (8 * 9)($4) ld $10, (8 * 10)($4) ld $11, (8 * 11)($4) ld $12, (8 * 12)($4) ld $13, (8 * 13)($4) ld $14, (8 * 14)($4) ld $15, (8 * 15)($4) ld $16, (8 * 16)($4) ld $17, (8 * 17)($4) ld $18, (8 * 18)($4) ld $19, (8 * 19)($4) ld $20, (8 * 20)($4) ld $21, (8 * 21)($4) ld $22, (8 * 22)($4) ld $23, (8 * 23)($4) ld $24, (8 * 24)($4) ld $25, (8 * 25)($4) ld $26, (8 * 26)($4) ld $27, (8 * 27)($4) ld $28, (8 * 28)($4) ld $29, (8 * 29)($4) ld $30, (8 * 30)($4) // load new pc into ra ld $31, (8 * 32)($4) // jump to ra, load a0 in the delay slot jr $31 ld $4, (8 * 4)($4) .set pop #elif defined(__sparc__) // // void libunwind::Registers_sparc_o32::jumpto() // // On entry: // thread_state pointer is in o0 // DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) ta 3 ldd [%o0 + 64], %l0 ldd [%o0 + 72], %l2 ldd [%o0 + 80], %l4 ldd [%o0 + 88], %l6 ldd [%o0 + 96], %i0 ldd [%o0 + 104], %i2 ldd [%o0 + 112], %i4 ldd [%o0 + 120], %i6 ld [%o0 + 60], %o7 jmp %o7 nop #elif defined(__riscv) && __riscv_xlen == 64 // // void libunwind::Registers_riscv::jumpto() // // On entry: // thread_state pointer is in a0 // .p2align 2 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) #if defined(__riscv_flen) && __riscv_flen == 64 fld f0, (8 * 32 + 8 * 0)(a0) fld f1, (8 * 32 + 8 * 1)(a0) fld f2, (8 * 32 + 8 * 2)(a0) fld f3, (8 * 32 + 8 * 3)(a0) fld f4, (8 * 32 + 8 * 4)(a0) fld f5, (8 * 32 + 8 * 5)(a0) fld f6, (8 * 32 + 8 * 6)(a0) fld f7, (8 * 32 + 8 * 7)(a0) fld f8, (8 * 32 + 8 * 8)(a0) fld f9, (8 * 32 + 8 * 9)(a0) fld f10, (8 * 32 + 8 * 10)(a0) fld f11, (8 * 32 + 8 * 11)(a0) fld f12, (8 * 32 + 8 * 12)(a0) fld f13, (8 * 32 + 8 * 13)(a0) fld f14, (8 * 32 + 8 * 14)(a0) fld f15, (8 * 32 + 8 * 15)(a0) fld f16, (8 * 32 + 8 * 16)(a0) fld f17, (8 * 32 + 8 * 17)(a0) fld f18, (8 * 32 + 8 * 18)(a0) fld f19, (8 * 32 + 8 * 19)(a0) fld f20, (8 * 32 + 8 * 20)(a0) fld f21, (8 * 32 + 8 * 21)(a0) fld f22, (8 * 32 + 8 * 22)(a0) fld f23, (8 * 32 + 8 * 23)(a0) fld f24, (8 * 32 + 8 * 24)(a0) fld f25, (8 * 32 + 8 * 25)(a0) fld f26, (8 * 32 + 8 * 26)(a0) fld f27, (8 * 32 + 8 * 27)(a0) fld f28, (8 * 32 + 8 * 28)(a0) fld f29, (8 * 32 + 8 * 29)(a0) fld f30, (8 * 32 + 8 * 30)(a0) fld f31, (8 * 32 + 8 * 31)(a0) #endif // x0 is zero ld x1, (8 * 1)(a0) ld x2, (8 * 2)(a0) ld x3, (8 * 3)(a0) ld x4, (8 * 4)(a0) ld x5, (8 * 5)(a0) ld x6, (8 * 6)(a0) ld x7, (8 * 7)(a0) ld x8, (8 * 8)(a0) ld x9, (8 * 9)(a0) // skip a0 for now ld x11, (8 * 11)(a0) ld x12, (8 * 12)(a0) ld x13, (8 * 13)(a0) ld x14, (8 * 14)(a0) ld x15, (8 * 15)(a0) ld x16, (8 * 16)(a0) ld x17, (8 * 17)(a0) ld x18, (8 * 18)(a0) ld x19, (8 * 19)(a0) ld x20, (8 * 20)(a0) ld x21, (8 * 21)(a0) ld x22, (8 * 22)(a0) ld x23, (8 * 23)(a0) ld x24, (8 * 24)(a0) ld x25, (8 * 25)(a0) ld x26, (8 * 26)(a0) ld x27, (8 * 27)(a0) ld x28, (8 * 28)(a0) ld x29, (8 * 29)(a0) ld x30, (8 * 30)(a0) ld x31, (8 * 31)(a0) ld x10, (8 * 10)(a0) // restore a0 ret // jump to ra #endif #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ NO_EXEC_STACK_DIRECTIVE Index: projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S (revision 357209) @@ -1,1143 +1,1063 @@ //===------------------------ UnwindRegistersSave.S -----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "assembly.h" .text #if !defined(__USING_SJLJ_EXCEPTIONS__) #if defined(__i386__) # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # + + # +-----------------------+ # + thread_state pointer + # +-----------------------+ # + return address + # +-----------------------+ <-- SP # + + # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) push %eax movl 8(%esp), %eax movl %ebx, 4(%eax) movl %ecx, 8(%eax) movl %edx, 12(%eax) movl %edi, 16(%eax) movl %esi, 20(%eax) movl %ebp, 24(%eax) movl %esp, %edx addl $8, %edx movl %edx, 28(%eax) # store what sp was at call site as esp # skip ss # skip eflags movl 4(%esp), %edx movl %edx, 40(%eax) # store return address as eip # skip cs # skip ds # skip es # skip fs # skip gs movl (%esp), %edx movl %edx, (%eax) # store original eax popl %eax xorl %eax, %eax # return UNW_ESUCCESS ret #elif defined(__x86_64__) # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in rdi # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) #if defined(_WIN64) #define PTR %rcx #define TMP %rdx #else #define PTR %rdi #define TMP %rsi #endif movq %rax, (PTR) movq %rbx, 8(PTR) movq %rcx, 16(PTR) movq %rdx, 24(PTR) movq %rdi, 32(PTR) movq %rsi, 40(PTR) movq %rbp, 48(PTR) movq %rsp, 56(PTR) addq $8, 56(PTR) movq %r8, 64(PTR) movq %r9, 72(PTR) movq %r10, 80(PTR) movq %r11, 88(PTR) movq %r12, 96(PTR) movq %r13,104(PTR) movq %r14,112(PTR) movq %r15,120(PTR) movq (%rsp),TMP movq TMP,128(PTR) # store return address as rip # skip rflags # skip cs # skip fs # skip gs #if defined(_WIN64) movdqu %xmm0,176(PTR) movdqu %xmm1,192(PTR) movdqu %xmm2,208(PTR) movdqu %xmm3,224(PTR) movdqu %xmm4,240(PTR) movdqu %xmm5,256(PTR) movdqu %xmm6,272(PTR) movdqu %xmm7,288(PTR) movdqu %xmm8,304(PTR) movdqu %xmm9,320(PTR) movdqu %xmm10,336(PTR) movdqu %xmm11,352(PTR) movdqu %xmm12,368(PTR) movdqu %xmm13,384(PTR) movdqu %xmm14,400(PTR) movdqu %xmm15,416(PTR) #endif xorl %eax, %eax # return UNW_ESUCCESS ret #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in a0 ($4) # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set push .set noat .set noreorder .set nomacro sw $1, (4 * 1)($4) sw $2, (4 * 2)($4) sw $3, (4 * 3)($4) sw $4, (4 * 4)($4) sw $5, (4 * 5)($4) sw $6, (4 * 6)($4) sw $7, (4 * 7)($4) sw $8, (4 * 8)($4) sw $9, (4 * 9)($4) sw $10, (4 * 10)($4) sw $11, (4 * 11)($4) sw $12, (4 * 12)($4) sw $13, (4 * 13)($4) sw $14, (4 * 14)($4) sw $15, (4 * 15)($4) sw $16, (4 * 16)($4) sw $17, (4 * 17)($4) sw $18, (4 * 18)($4) sw $19, (4 * 19)($4) sw $20, (4 * 20)($4) sw $21, (4 * 21)($4) sw $22, (4 * 22)($4) sw $23, (4 * 23)($4) sw $24, (4 * 24)($4) sw $25, (4 * 25)($4) sw $26, (4 * 26)($4) sw $27, (4 * 27)($4) sw $28, (4 * 28)($4) sw $29, (4 * 29)($4) sw $30, (4 * 30)($4) sw $31, (4 * 31)($4) # Store return address to pc sw $31, (4 * 32)($4) # hi and lo mfhi $8 sw $8, (4 * 33)($4) mflo $8 sw $8, (4 * 34)($4) #ifdef __mips_hard_float #if __mips_fpr != 64 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) sdc1 $f4, (4 * 36 + 8 * 4)($4) sdc1 $f6, (4 * 36 + 8 * 6)($4) sdc1 $f8, (4 * 36 + 8 * 8)($4) sdc1 $f10, (4 * 36 + 8 * 10)($4) sdc1 $f12, (4 * 36 + 8 * 12)($4) sdc1 $f14, (4 * 36 + 8 * 14)($4) sdc1 $f16, (4 * 36 + 8 * 16)($4) sdc1 $f18, (4 * 36 + 8 * 18)($4) sdc1 $f20, (4 * 36 + 8 * 20)($4) sdc1 $f22, (4 * 36 + 8 * 22)($4) sdc1 $f24, (4 * 36 + 8 * 24)($4) sdc1 $f26, (4 * 36 + 8 * 26)($4) sdc1 $f28, (4 * 36 + 8 * 28)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) #else sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) sdc1 $f3, (4 * 36 + 8 * 3)($4) sdc1 $f4, (4 * 36 + 8 * 4)($4) sdc1 $f5, (4 * 36 + 8 * 5)($4) sdc1 $f6, (4 * 36 + 8 * 6)($4) sdc1 $f7, (4 * 36 + 8 * 7)($4) sdc1 $f8, (4 * 36 + 8 * 8)($4) sdc1 $f9, (4 * 36 + 8 * 9)($4) sdc1 $f10, (4 * 36 + 8 * 10)($4) sdc1 $f11, (4 * 36 + 8 * 11)($4) sdc1 $f12, (4 * 36 + 8 * 12)($4) sdc1 $f13, (4 * 36 + 8 * 13)($4) sdc1 $f14, (4 * 36 + 8 * 14)($4) sdc1 $f15, (4 * 36 + 8 * 15)($4) sdc1 $f16, (4 * 36 + 8 * 16)($4) sdc1 $f17, (4 * 36 + 8 * 17)($4) sdc1 $f18, (4 * 36 + 8 * 18)($4) sdc1 $f19, (4 * 36 + 8 * 19)($4) sdc1 $f20, (4 * 36 + 8 * 20)($4) sdc1 $f21, (4 * 36 + 8 * 21)($4) sdc1 $f22, (4 * 36 + 8 * 22)($4) sdc1 $f23, (4 * 36 + 8 * 23)($4) sdc1 $f24, (4 * 36 + 8 * 24)($4) sdc1 $f25, (4 * 36 + 8 * 25)($4) sdc1 $f26, (4 * 36 + 8 * 26)($4) sdc1 $f27, (4 * 36 + 8 * 27)($4) sdc1 $f28, (4 * 36 + 8 * 28)($4) sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) #endif #endif jr $31 # return UNW_ESUCCESS or $2, $0, $0 .set pop #elif defined(__mips64) # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in a0 ($4) # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set push .set noat .set noreorder .set nomacro sd $1, (8 * 1)($4) sd $2, (8 * 2)($4) sd $3, (8 * 3)($4) sd $4, (8 * 4)($4) sd $5, (8 * 5)($4) sd $6, (8 * 6)($4) sd $7, (8 * 7)($4) sd $8, (8 * 8)($4) sd $9, (8 * 9)($4) sd $10, (8 * 10)($4) sd $11, (8 * 11)($4) sd $12, (8 * 12)($4) sd $13, (8 * 13)($4) sd $14, (8 * 14)($4) sd $15, (8 * 15)($4) sd $16, (8 * 16)($4) sd $17, (8 * 17)($4) sd $18, (8 * 18)($4) sd $19, (8 * 19)($4) sd $20, (8 * 20)($4) sd $21, (8 * 21)($4) sd $22, (8 * 22)($4) sd $23, (8 * 23)($4) sd $24, (8 * 24)($4) sd $25, (8 * 25)($4) sd $26, (8 * 26)($4) sd $27, (8 * 27)($4) sd $28, (8 * 28)($4) sd $29, (8 * 29)($4) sd $30, (8 * 30)($4) sd $31, (8 * 31)($4) # Store return address to pc sd $31, (8 * 32)($4) # hi and lo mfhi $8 sd $8, (8 * 33)($4) mflo $8 sd $8, (8 * 34)($4) #ifdef __mips_hard_float sdc1 $f0, (8 * 35)($4) sdc1 $f1, (8 * 36)($4) sdc1 $f2, (8 * 37)($4) sdc1 $f3, (8 * 38)($4) sdc1 $f4, (8 * 39)($4) sdc1 $f5, (8 * 40)($4) sdc1 $f6, (8 * 41)($4) sdc1 $f7, (8 * 42)($4) sdc1 $f8, (8 * 43)($4) sdc1 $f9, (8 * 44)($4) sdc1 $f10, (8 * 45)($4) sdc1 $f11, (8 * 46)($4) sdc1 $f12, (8 * 47)($4) sdc1 $f13, (8 * 48)($4) sdc1 $f14, (8 * 49)($4) sdc1 $f15, (8 * 50)($4) sdc1 $f16, (8 * 51)($4) sdc1 $f17, (8 * 52)($4) sdc1 $f18, (8 * 53)($4) sdc1 $f19, (8 * 54)($4) sdc1 $f20, (8 * 55)($4) sdc1 $f21, (8 * 56)($4) sdc1 $f22, (8 * 57)($4) sdc1 $f23, (8 * 58)($4) sdc1 $f24, (8 * 59)($4) sdc1 $f25, (8 * 60)($4) sdc1 $f26, (8 * 61)($4) sdc1 $f27, (8 * 62)($4) sdc1 $f28, (8 * 63)($4) sdc1 $f29, (8 * 64)($4) sdc1 $f30, (8 * 65)($4) sdc1 $f31, (8 * 66)($4) #endif jr $31 # return UNW_ESUCCESS or $2, $0, $0 .set pop # elif defined(__mips__) # # extern int __unw_getcontext(unw_context_t* thread_state) # # Just trap for the time being. DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) teq $0, $0 #elif defined(__powerpc64__) // // extern int __unw_getcontext(unw_context_t* thread_state) // // On entry: // thread_state pointer is in r3 // DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) // store register (GPR) #define PPC64_STR(n) \ std %r##n, (8 * (n + 2))(%r3) // save GPRs PPC64_STR(0) mflr %r0 std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 PPC64_STR(1) PPC64_STR(2) PPC64_STR(3) PPC64_STR(4) PPC64_STR(5) PPC64_STR(6) PPC64_STR(7) PPC64_STR(8) PPC64_STR(9) PPC64_STR(10) PPC64_STR(11) PPC64_STR(12) PPC64_STR(13) PPC64_STR(14) PPC64_STR(15) PPC64_STR(16) PPC64_STR(17) PPC64_STR(18) PPC64_STR(19) PPC64_STR(20) PPC64_STR(21) PPC64_STR(22) PPC64_STR(23) PPC64_STR(24) PPC64_STR(25) PPC64_STR(26) PPC64_STR(27) PPC64_STR(28) PPC64_STR(29) PPC64_STR(30) PPC64_STR(31) mfcr %r0 std %r0, PPC64_OFFS_CR(%r3) mfxer %r0 std %r0, PPC64_OFFS_XER(%r3) mflr %r0 std %r0, PPC64_OFFS_LR(%r3) mfctr %r0 std %r0, PPC64_OFFS_CTR(%r3) mfvrsave %r0 std %r0, PPC64_OFFS_VRSAVE(%r3) #ifdef PPC64_HAS_VMX // save VS registers // (note that this also saves floating point registers and V registers, // because part of VS is mapped to these registers) addi %r4, %r3, PPC64_OFFS_FP // store VS register #define PPC64_STVS(n) \ stxvd2x %vs##n, 0, %r4 ;\ addi %r4, %r4, 16 PPC64_STVS(0) PPC64_STVS(1) PPC64_STVS(2) PPC64_STVS(3) PPC64_STVS(4) PPC64_STVS(5) PPC64_STVS(6) PPC64_STVS(7) PPC64_STVS(8) PPC64_STVS(9) PPC64_STVS(10) PPC64_STVS(11) PPC64_STVS(12) PPC64_STVS(13) PPC64_STVS(14) PPC64_STVS(15) PPC64_STVS(16) PPC64_STVS(17) PPC64_STVS(18) PPC64_STVS(19) PPC64_STVS(20) PPC64_STVS(21) PPC64_STVS(22) PPC64_STVS(23) PPC64_STVS(24) PPC64_STVS(25) PPC64_STVS(26) PPC64_STVS(27) PPC64_STVS(28) PPC64_STVS(29) PPC64_STVS(30) PPC64_STVS(31) PPC64_STVS(32) PPC64_STVS(33) PPC64_STVS(34) PPC64_STVS(35) PPC64_STVS(36) PPC64_STVS(37) PPC64_STVS(38) PPC64_STVS(39) PPC64_STVS(40) PPC64_STVS(41) PPC64_STVS(42) PPC64_STVS(43) PPC64_STVS(44) PPC64_STVS(45) PPC64_STVS(46) PPC64_STVS(47) PPC64_STVS(48) PPC64_STVS(49) PPC64_STVS(50) PPC64_STVS(51) PPC64_STVS(52) PPC64_STVS(53) PPC64_STVS(54) PPC64_STVS(55) PPC64_STVS(56) PPC64_STVS(57) PPC64_STVS(58) PPC64_STVS(59) PPC64_STVS(60) PPC64_STVS(61) PPC64_STVS(62) PPC64_STVS(63) #else // store FP register #define PPC64_STF(n) \ stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) // save float registers PPC64_STF(0) PPC64_STF(1) PPC64_STF(2) PPC64_STF(3) PPC64_STF(4) PPC64_STF(5) PPC64_STF(6) PPC64_STF(7) PPC64_STF(8) PPC64_STF(9) PPC64_STF(10) PPC64_STF(11) PPC64_STF(12) PPC64_STF(13) PPC64_STF(14) PPC64_STF(15) PPC64_STF(16) PPC64_STF(17) PPC64_STF(18) PPC64_STF(19) PPC64_STF(20) PPC64_STF(21) PPC64_STF(22) PPC64_STF(23) PPC64_STF(24) PPC64_STF(25) PPC64_STF(26) PPC64_STF(27) PPC64_STF(28) PPC64_STF(29) PPC64_STF(30) PPC64_STF(31) // save vector registers // Use 16-bytes below the stack pointer as an // aligned buffer to save each vector register. // Note that the stack pointer is always 16-byte aligned. subi %r4, %r1, 16 #define PPC64_STV_UNALIGNED(n) \ stvx %v##n, 0, %r4 ;\ ld %r5, 0(%r4) ;\ std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\ ld %r5, 8(%r4) ;\ std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3) PPC64_STV_UNALIGNED(0) PPC64_STV_UNALIGNED(1) PPC64_STV_UNALIGNED(2) PPC64_STV_UNALIGNED(3) PPC64_STV_UNALIGNED(4) PPC64_STV_UNALIGNED(5) PPC64_STV_UNALIGNED(6) PPC64_STV_UNALIGNED(7) PPC64_STV_UNALIGNED(8) PPC64_STV_UNALIGNED(9) PPC64_STV_UNALIGNED(10) PPC64_STV_UNALIGNED(11) PPC64_STV_UNALIGNED(12) PPC64_STV_UNALIGNED(13) PPC64_STV_UNALIGNED(14) PPC64_STV_UNALIGNED(15) PPC64_STV_UNALIGNED(16) PPC64_STV_UNALIGNED(17) PPC64_STV_UNALIGNED(18) PPC64_STV_UNALIGNED(19) PPC64_STV_UNALIGNED(20) PPC64_STV_UNALIGNED(21) PPC64_STV_UNALIGNED(22) PPC64_STV_UNALIGNED(23) PPC64_STV_UNALIGNED(24) PPC64_STV_UNALIGNED(25) PPC64_STV_UNALIGNED(26) PPC64_STV_UNALIGNED(27) PPC64_STV_UNALIGNED(28) PPC64_STV_UNALIGNED(29) PPC64_STV_UNALIGNED(30) PPC64_STV_UNALIGNED(31) #endif li %r3, 0 // return UNW_ESUCCESS blr #elif defined(__ppc__) // -// extern int __unw_getcontext(unw_context_t* thread_state) +// extern int unw_getcontext(unw_context_t* thread_state) // // On entry: // thread_state pointer is in r3 // DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stw %r0, 8(%r3) mflr %r0 stw %r0, 0(%r3) // store lr as ssr0 stw %r1, 12(%r3) stw %r2, 16(%r3) stw %r3, 20(%r3) stw %r4, 24(%r3) stw %r5, 28(%r3) stw %r6, 32(%r3) stw %r7, 36(%r3) stw %r8, 40(%r3) stw %r9, 44(%r3) stw %r10, 48(%r3) stw %r11, 52(%r3) stw %r12, 56(%r3) stw %r13, 60(%r3) stw %r14, 64(%r3) stw %r15, 68(%r3) stw %r16, 72(%r3) stw %r17, 76(%r3) stw %r18, 80(%r3) stw %r19, 84(%r3) stw %r20, 88(%r3) stw %r21, 92(%r3) stw %r22, 96(%r3) stw %r23,100(%r3) stw %r24,104(%r3) stw %r25,108(%r3) stw %r26,112(%r3) stw %r27,116(%r3) stw %r28,120(%r3) stw %r29,124(%r3) stw %r30,128(%r3) stw %r31,132(%r3) // save VRSave register mfspr %r0, 256 stw %r0, 156(%r3) // save CR registers mfcr %r0 stw %r0, 136(%r3) // save CTR register mfctr %r0 stw %r0, 148(%r3) // save float registers stfd %f0, 160(%r3) stfd %f1, 168(%r3) stfd %f2, 176(%r3) stfd %f3, 184(%r3) stfd %f4, 192(%r3) stfd %f5, 200(%r3) stfd %f6, 208(%r3) stfd %f7, 216(%r3) stfd %f8, 224(%r3) stfd %f9, 232(%r3) stfd %f10,240(%r3) stfd %f11,248(%r3) stfd %f12,256(%r3) stfd %f13,264(%r3) stfd %f14,272(%r3) stfd %f15,280(%r3) stfd %f16,288(%r3) stfd %f17,296(%r3) stfd %f18,304(%r3) stfd %f19,312(%r3) stfd %f20,320(%r3) stfd %f21,328(%r3) stfd %f22,336(%r3) stfd %f23,344(%r3) stfd %f24,352(%r3) stfd %f25,360(%r3) stfd %f26,368(%r3) stfd %f27,376(%r3) stfd %f28,384(%r3) stfd %f29,392(%r3) stfd %f30,400(%r3) stfd %f31,408(%r3) // save vector registers subi %r4, %r1, 16 rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits // r4 is now a 16-byte aligned pointer into the red zone #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ stvx _vec, 0, %r4 SEPARATOR \ lwz %r5, 0(%r4) SEPARATOR \ stw %r5, _offset(%r3) SEPARATOR \ lwz %r5, 4(%r4) SEPARATOR \ stw %r5, _offset+4(%r3) SEPARATOR \ lwz %r5, 8(%r4) SEPARATOR \ stw %r5, _offset+8(%r3) SEPARATOR \ lwz %r5, 12(%r4) SEPARATOR \ stw %r5, _offset+12(%r3) SAVE_VECTOR_UNALIGNED( %v0, 424+0x000) SAVE_VECTOR_UNALIGNED( %v1, 424+0x010) SAVE_VECTOR_UNALIGNED( %v2, 424+0x020) SAVE_VECTOR_UNALIGNED( %v3, 424+0x030) SAVE_VECTOR_UNALIGNED( %v4, 424+0x040) SAVE_VECTOR_UNALIGNED( %v5, 424+0x050) SAVE_VECTOR_UNALIGNED( %v6, 424+0x060) SAVE_VECTOR_UNALIGNED( %v7, 424+0x070) SAVE_VECTOR_UNALIGNED( %v8, 424+0x080) SAVE_VECTOR_UNALIGNED( %v9, 424+0x090) SAVE_VECTOR_UNALIGNED(%v10, 424+0x0A0) SAVE_VECTOR_UNALIGNED(%v11, 424+0x0B0) SAVE_VECTOR_UNALIGNED(%v12, 424+0x0C0) SAVE_VECTOR_UNALIGNED(%v13, 424+0x0D0) SAVE_VECTOR_UNALIGNED(%v14, 424+0x0E0) SAVE_VECTOR_UNALIGNED(%v15, 424+0x0F0) SAVE_VECTOR_UNALIGNED(%v16, 424+0x100) SAVE_VECTOR_UNALIGNED(%v17, 424+0x110) SAVE_VECTOR_UNALIGNED(%v18, 424+0x120) SAVE_VECTOR_UNALIGNED(%v19, 424+0x130) SAVE_VECTOR_UNALIGNED(%v20, 424+0x140) SAVE_VECTOR_UNALIGNED(%v21, 424+0x150) SAVE_VECTOR_UNALIGNED(%v22, 424+0x160) SAVE_VECTOR_UNALIGNED(%v23, 424+0x170) SAVE_VECTOR_UNALIGNED(%v24, 424+0x180) SAVE_VECTOR_UNALIGNED(%v25, 424+0x190) SAVE_VECTOR_UNALIGNED(%v26, 424+0x1A0) SAVE_VECTOR_UNALIGNED(%v27, 424+0x1B0) SAVE_VECTOR_UNALIGNED(%v28, 424+0x1C0) SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) li %r3, 0 // return UNW_ESUCCESS blr #elif defined(__arm64__) || defined(__aarch64__) // // extern int __unw_getcontext(unw_context_t* thread_state) // // On entry: // thread_state pointer is in x0 // .p2align 2 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stp x0, x1, [x0, #0x000] stp x2, x3, [x0, #0x010] stp x4, x5, [x0, #0x020] stp x6, x7, [x0, #0x030] stp x8, x9, [x0, #0x040] stp x10,x11, [x0, #0x050] stp x12,x13, [x0, #0x060] stp x14,x15, [x0, #0x070] stp x16,x17, [x0, #0x080] stp x18,x19, [x0, #0x090] stp x20,x21, [x0, #0x0A0] stp x22,x23, [x0, #0x0B0] stp x24,x25, [x0, #0x0C0] stp x26,x27, [x0, #0x0D0] stp x28,x29, [x0, #0x0E0] str x30, [x0, #0x0F0] mov x1,sp str x1, [x0, #0x0F8] str x30, [x0, #0x100] // store return address as pc // skip cpsr stp d0, d1, [x0, #0x110] stp d2, d3, [x0, #0x120] stp d4, d5, [x0, #0x130] stp d6, d7, [x0, #0x140] stp d8, d9, [x0, #0x150] stp d10,d11, [x0, #0x160] stp d12,d13, [x0, #0x170] stp d14,d15, [x0, #0x180] stp d16,d17, [x0, #0x190] stp d18,d19, [x0, #0x1A0] stp d20,d21, [x0, #0x1B0] stp d22,d23, [x0, #0x1C0] stp d24,d25, [x0, #0x1D0] stp d26,d27, [x0, #0x1E0] stp d28,d29, [x0, #0x1F0] str d30, [x0, #0x200] str d31, [x0, #0x208] mov x0, #0 // return UNW_ESUCCESS ret #elif defined(__arm__) && !defined(__APPLE__) #if !defined(__ARM_ARCH_ISA_ARM) #if (__ARM_ARCH_ISA_THUMB == 2) .syntax unified #endif .thumb #endif @ @ extern int __unw_getcontext(unw_context_t* thread_state) @ @ On entry: @ thread_state pointer is in r0 @ @ Per EHABI #4.7 this only saves the core integer registers. @ EHABI #7.4.5 notes that in general all VRS registers should be restored @ however this is very hard to do for VFP registers because it is unknown @ to the library how many registers are implemented by the architecture. @ Instead, VFP registers are demand saved by logic external to __unw_getcontext. @ .p2align 2 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 stm r0!, {r0-r7} mov r1, r8 mov r2, r9 mov r3, r10 stm r0!, {r1-r3} mov r1, r11 mov r2, sp mov r3, lr str r1, [r0, #0] @ r11 @ r12 does not need storing, it it the intra-procedure-call scratch register str r2, [r0, #8] @ sp str r3, [r0, #12] @ lr str r3, [r0, #16] @ store return address as pc @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. @ It is safe to use here though because we are about to return, and cpsr is @ not expected to be preserved. movs r0, #0 @ return UNW_ESUCCESS #else @ 32bit thumb-2 restrictions for stm: @ . the sp (r13) cannot be in the list @ . the pc (r15) cannot be in the list in an STM instruction stm r0, {r0-r12} str sp, [r0, #52] str lr, [r0, #56] str lr, [r0, #60] @ store return address as pc mov r0, #0 @ return UNW_ESUCCESS #endif JMP(lr) @ @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3-d16 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv) vstmia r0, {d0-d15} JMP(lr) @ @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3-d16 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv) vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia JMP(lr) @ @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .fpu vfpv3 #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv) @ VFP and iwMMX instructions are only available when compiling with the flags @ that enable them. We do not want to do that in the library (because we do not @ want the compiler to generate instructions that access those) but this is @ only accessed if the personality routine needs these registers. Use of @ these registers implies they are, actually, available on the target, so @ it's ok to execute. @ So, generate the instructions using the corresponding coprocessor mnemonic. vstmia r0, {d16-d31} JMP(lr) #if defined(_LIBUNWIND_ARM_WMMX) @ @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .arch armv5te #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv) stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8 JMP(lr) @ @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values) @ @ On entry: @ values pointer is in r0 @ .p2align 2 #if defined(__ELF__) .arch armv5te #endif DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4 JMP(lr) #endif #elif defined(__or1k__) # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in r3 # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) l.sw 0(r3), r0 l.sw 4(r3), r1 l.sw 8(r3), r2 l.sw 12(r3), r3 l.sw 16(r3), r4 l.sw 20(r3), r5 l.sw 24(r3), r6 l.sw 28(r3), r7 l.sw 32(r3), r8 l.sw 36(r3), r9 l.sw 40(r3), r10 l.sw 44(r3), r11 l.sw 48(r3), r12 l.sw 52(r3), r13 l.sw 56(r3), r14 l.sw 60(r3), r15 l.sw 64(r3), r16 l.sw 68(r3), r17 l.sw 72(r3), r18 l.sw 76(r3), r19 l.sw 80(r3), r20 l.sw 84(r3), r21 l.sw 88(r3), r22 l.sw 92(r3), r23 l.sw 96(r3), r24 l.sw 100(r3), r25 l.sw 104(r3), r26 l.sw 108(r3), r27 l.sw 112(r3), r28 l.sw 116(r3), r29 l.sw 120(r3), r30 l.sw 124(r3), r31 # store ra to pc l.sw 128(r3), r9 # zero epcr l.sw 132(r3), r0 - -#elif defined(__riscv) - -# -# extern int __unw_getcontext(unw_context_t* thread_state) -# -# On entry: -# thread_state pointer is in a0 -# -DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) - // x0 is zero - sd x1, (8 * 1)(a0) - sd x2, (8 * 2)(a0) - sd x3, (8 * 3)(a0) - sd x4, (8 * 4)(a0) - sd x5, (8 * 5)(a0) - sd x6, (8 * 6)(a0) - sd x7, (8 * 7)(a0) - sd x8, (8 * 8)(a0) - sd x9, (8 * 9)(a0) - sd x10, (8 * 10)(a0) - sd x11, (8 * 11)(a0) - sd x12, (8 * 12)(a0) - sd x13, (8 * 13)(a0) - sd x14, (8 * 14)(a0) - sd x15, (8 * 15)(a0) - sd x16, (8 * 16)(a0) - sd x17, (8 * 17)(a0) - sd x18, (8 * 18)(a0) - sd x19, (8 * 19)(a0) - sd x20, (8 * 20)(a0) - sd x21, (8 * 21)(a0) - sd x22, (8 * 22)(a0) - sd x23, (8 * 23)(a0) - sd x24, (8 * 24)(a0) - sd x25, (8 * 25)(a0) - sd x26, (8 * 26)(a0) - sd x27, (8 * 27)(a0) - sd x28, (8 * 28)(a0) - sd x29, (8 * 29)(a0) - sd x30, (8 * 30)(a0) - sd x31, (8 * 31)(a0) - -#ifdef __riscv_float_abi_double - fsd f0, (8 * 32 + 8 * 0)(a0) - fsd f1, (8 * 32 + 8 * 1)(a0) - fsd f2, (8 * 32 + 8 * 2)(a0) - fsd f3, (8 * 32 + 8 * 3)(a0) - fsd f4, (8 * 32 + 8 * 4)(a0) - fsd f5, (8 * 32 + 8 * 5)(a0) - fsd f6, (8 * 32 + 8 * 6)(a0) - fsd f7, (8 * 32 + 8 * 7)(a0) - fsd f8, (8 * 32 + 8 * 8)(a0) - fsd f9, (8 * 32 + 8 * 9)(a0) - fsd f10, (8 * 32 + 8 * 10)(a0) - fsd f11, (8 * 32 + 8 * 11)(a0) - fsd f12, (8 * 32 + 8 * 12)(a0) - fsd f13, (8 * 32 + 8 * 13)(a0) - fsd f14, (8 * 32 + 8 * 14)(a0) - fsd f15, (8 * 32 + 8 * 15)(a0) - fsd f16, (8 * 32 + 8 * 16)(a0) - fsd f17, (8 * 32 + 8 * 17)(a0) - fsd f18, (8 * 32 + 8 * 18)(a0) - fsd f19, (8 * 32 + 8 * 19)(a0) - fsd f20, (8 * 32 + 8 * 20)(a0) - fsd f21, (8 * 32 + 8 * 21)(a0) - fsd f22, (8 * 32 + 8 * 22)(a0) - fsd f23, (8 * 32 + 8 * 23)(a0) - fsd f24, (8 * 32 + 8 * 24)(a0) - fsd f25, (8 * 32 + 8 * 25)(a0) - fsd f26, (8 * 32 + 8 * 26)(a0) - fsd f27, (8 * 32 + 8 * 27)(a0) - fsd f28, (8 * 32 + 8 * 28)(a0) - fsd f29, (8 * 32 + 8 * 29)(a0) - fsd f30, (8 * 32 + 8 * 30)(a0) - fsd f31, (8 * 32 + 8 * 31)(a0) -#endif - - li a0, 0 // return UNW_ESUCCESS - ret // jump to ra #elif defined(__sparc__) # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in o0 # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) ta 3 add %o7, 8, %o7 std %g0, [%o0 + 0] std %g2, [%o0 + 8] std %g4, [%o0 + 16] std %g6, [%o0 + 24] std %o0, [%o0 + 32] std %o2, [%o0 + 40] std %o4, [%o0 + 48] std %o6, [%o0 + 56] std %l0, [%o0 + 64] std %l2, [%o0 + 72] std %l4, [%o0 + 80] std %l6, [%o0 + 88] std %i0, [%o0 + 96] std %i2, [%o0 + 104] std %i4, [%o0 + 112] std %i6, [%o0 + 120] jmp %o7 clr %o0 // return UNW_ESUCCESS #elif defined(__riscv) && __riscv_xlen == 64 # # extern int __unw_getcontext(unw_context_t* thread_state) # # On entry: # thread_state pointer is in a0 # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) // x0 is zero sd x1, (8 * 1)(a0) sd x2, (8 * 2)(a0) sd x3, (8 * 3)(a0) sd x4, (8 * 4)(a0) sd x5, (8 * 5)(a0) sd x6, (8 * 6)(a0) sd x7, (8 * 7)(a0) sd x8, (8 * 8)(a0) sd x9, (8 * 9)(a0) sd x10, (8 * 10)(a0) sd x11, (8 * 11)(a0) sd x12, (8 * 12)(a0) sd x13, (8 * 13)(a0) sd x14, (8 * 14)(a0) sd x15, (8 * 15)(a0) sd x16, (8 * 16)(a0) sd x17, (8 * 17)(a0) sd x18, (8 * 18)(a0) sd x19, (8 * 19)(a0) sd x20, (8 * 20)(a0) sd x21, (8 * 21)(a0) sd x22, (8 * 22)(a0) sd x23, (8 * 23)(a0) sd x24, (8 * 24)(a0) sd x25, (8 * 25)(a0) sd x26, (8 * 26)(a0) sd x27, (8 * 27)(a0) sd x28, (8 * 28)(a0) sd x29, (8 * 29)(a0) sd x30, (8 * 30)(a0) sd x31, (8 * 31)(a0) #if defined(__riscv_flen) && __riscv_flen == 64 fsd f0, (8 * 32 + 8 * 0)(a0) fsd f1, (8 * 32 + 8 * 1)(a0) fsd f2, (8 * 32 + 8 * 2)(a0) fsd f3, (8 * 32 + 8 * 3)(a0) fsd f4, (8 * 32 + 8 * 4)(a0) fsd f5, (8 * 32 + 8 * 5)(a0) fsd f6, (8 * 32 + 8 * 6)(a0) fsd f7, (8 * 32 + 8 * 7)(a0) fsd f8, (8 * 32 + 8 * 8)(a0) fsd f9, (8 * 32 + 8 * 9)(a0) fsd f10, (8 * 32 + 8 * 10)(a0) fsd f11, (8 * 32 + 8 * 11)(a0) fsd f12, (8 * 32 + 8 * 12)(a0) fsd f13, (8 * 32 + 8 * 13)(a0) fsd f14, (8 * 32 + 8 * 14)(a0) fsd f15, (8 * 32 + 8 * 15)(a0) fsd f16, (8 * 32 + 8 * 16)(a0) fsd f17, (8 * 32 + 8 * 17)(a0) fsd f18, (8 * 32 + 8 * 18)(a0) fsd f19, (8 * 32 + 8 * 19)(a0) fsd f20, (8 * 32 + 8 * 20)(a0) fsd f21, (8 * 32 + 8 * 21)(a0) fsd f22, (8 * 32 + 8 * 22)(a0) fsd f23, (8 * 32 + 8 * 23)(a0) fsd f24, (8 * 32 + 8 * 24)(a0) fsd f25, (8 * 32 + 8 * 25)(a0) fsd f26, (8 * 32 + 8 * 26)(a0) fsd f27, (8 * 32 + 8 * 27)(a0) fsd f28, (8 * 32 + 8 * 28)(a0) fsd f29, (8 * 32 + 8 * 29)(a0) fsd f30, (8 * 32 + 8 * 30)(a0) fsd f31, (8 * 32 + 8 * 31)(a0) #endif li a0, 0 // return UNW_ESUCCESS ret // jump to ra #endif WEAK_ALIAS(__unw_getcontext, unw_getcontext) #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ NO_EXEC_STACK_DIRECTIVE Index: projects/clang1000-import/contrib/llvm-project/libunwind/src/libunwind.cpp =================================================================== --- projects/clang1000-import/contrib/llvm-project/libunwind/src/libunwind.cpp (revision 357208) +++ projects/clang1000-import/contrib/llvm-project/libunwind/src/libunwind.cpp (revision 357209) @@ -1,326 +1,324 @@ //===--------------------------- libunwind.cpp ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // // Implements unw_* functions from // //===----------------------------------------------------------------------===// #include #include "libunwind_ext.h" #include "config.h" #include #if !defined(__USING_SJLJ_EXCEPTIONS__) #include "AddressSpace.hpp" #include "UnwindCursor.hpp" using namespace libunwind; /// internal object to represent this processes address space LocalAddressSpace LocalAddressSpace::sThisAddressSpace; _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace; /// Create a cursor of a thread in this process given 'context' recorded by /// __unw_getcontext(). _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, unw_context_t *context) { _LIBUNWIND_TRACE_API("__unw_init_local(cursor=%p, context=%p)", static_cast(cursor), static_cast(context)); #if defined(__i386__) # define REGISTER_KIND Registers_x86 #elif defined(__x86_64__) # define REGISTER_KIND Registers_x86_64 #elif defined(__powerpc64__) # define REGISTER_KIND Registers_ppc64 #elif defined(__ppc__) # define REGISTER_KIND Registers_ppc #elif defined(__aarch64__) # define REGISTER_KIND Registers_arm64 #elif defined(__arm__) # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k -#elif defined(__riscv) -# define REGISTER_KIND Registers_riscv #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define REGISTER_KIND Registers_mips_o32 #elif defined(__mips64) # define REGISTER_KIND Registers_mips_newabi #elif defined(__mips__) # warning The MIPS architecture is not supported with this ABI and environment! #elif defined(__sparc__) # define REGISTER_KIND Registers_sparc #elif defined(__riscv) && __riscv_xlen == 64 # define REGISTER_KIND Registers_riscv #else # error Architecture not supported #endif // Use "placement new" to allocate UnwindCursor in the cursor buffer. new (reinterpret_cast *>(cursor)) UnwindCursor( context, LocalAddressSpace::sThisAddressSpace); #undef REGISTER_KIND AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->setInfoBasedOnIPRegister(); return UNW_ESUCCESS; } _LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local) /// Get value of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t *value) { _LIBUNWIND_TRACE_API("__unw_get_reg(cursor=%p, regNum=%d, &value=%p)", static_cast(cursor), regNum, static_cast(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { *value = co->getReg(regNum); return UNW_ESUCCESS; } return UNW_EBADREG; } _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) { _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); // specical 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); // If the original call expects stack adjustment, perform this now. // Normal frame unwinding would have included the offset already in the // CFA computation. // Note: for PA-RISC and other platforms where the stack grows up, // this should actually be - info.gp. LLVM doesn't currently support // any such platforms and Clang doesn't export a macro for them. if (info.gp) co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); } return UNW_ESUCCESS; } return UNW_EBADREG; } _LIBUNWIND_WEAK_ALIAS(__unw_set_reg, unw_set_reg) /// Get value of specified float register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t *value) { _LIBUNWIND_TRACE_API("__unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)", static_cast(cursor), regNum, static_cast(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validFloatReg(regNum)) { *value = co->getFloatReg(regNum); return UNW_ESUCCESS; } return UNW_EBADREG; } _LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg) /// Set value of specified float register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { #if defined(_LIBUNWIND_ARM_EHABI) _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", static_cast(cursor), regNum, value); #else _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%g)", static_cast(cursor), regNum, value); #endif AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validFloatReg(regNum)) { co->setFloatReg(regNum, value); return UNW_ESUCCESS; } return UNW_EBADREG; } _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg) /// Move cursor to next frame. _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->step(); } _LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step) /// Get unwind info at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, unw_proc_info_t *info) { _LIBUNWIND_TRACE_API("__unw_get_proc_info(cursor=%p, &info=%p)", static_cast(cursor), static_cast(info)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->getInfo(info); if (info->end_ip == 0) return UNW_ENOINFO; return UNW_ESUCCESS; } _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) /// 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)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->jumpto(); return UNW_EUNSPEC; } _LIBUNWIND_WEAK_ALIAS(__unw_resume, unw_resume) /// Get name of function at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_proc_name(unw_cursor_t *cursor, char *buf, size_t bufLen, unw_word_t *offset) { _LIBUNWIND_TRACE_API("__unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)", static_cast(cursor), static_cast(buf), static_cast(bufLen)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->getFunctionName(buf, bufLen, offset)) return UNW_ESUCCESS; return UNW_EUNSPEC; } _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name, unw_get_proc_name) /// Checks if a register is a floating-point register. _LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { _LIBUNWIND_TRACE_API("__unw_is_fpreg(cursor=%p, regNum=%d)", static_cast(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->validFloatReg(regNum); } _LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg) /// Checks if a register is a floating-point register. _LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor, unw_regnum_t regNum) { _LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)", static_cast(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->getRegisterName(regNum); } _LIBUNWIND_WEAK_ALIAS(__unw_regname, unw_regname) /// Checks if current frame is signal trampoline. _LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_is_signal_frame(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->isSignalFrame(); } _LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame) #ifdef __arm__ // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD _LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_get_fpreg_save_vfp_as_X(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->saveVFPAsX(); } _LIBUNWIND_WEAK_ALIAS(__unw_save_vfp_as_X, unw_save_vfp_as_X) #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) /// SPI: walks cached DWARF entries _LIBUNWIND_HIDDEN void __unw_iterate_dwarf_unwind_cache(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { _LIBUNWIND_TRACE_API("__unw_iterate_dwarf_unwind_cache(func=%p)", reinterpret_cast(func)); DwarfFDECache::iterateCacheEntries(func); } _LIBUNWIND_WEAK_ALIAS(__unw_iterate_dwarf_unwind_cache, unw_iterate_dwarf_unwind_cache) /// IPI: for __register_frame() void __unw_add_dynamic_fde(unw_word_t fde) { CFI_Parser::FDE_Info fdeInfo; CFI_Parser::CIE_Info cieInfo; const char *message = CFI_Parser::decodeFDE( LocalAddressSpace::sThisAddressSpace, (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo); if (message == NULL) { // dynamically registered FDEs don't have a mach_header group they are in. // Use fde as mh_group unw_word_t mh_group = fdeInfo.fdeStart; DwarfFDECache::add((LocalAddressSpace::pint_t)mh_group, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart); } else { _LIBUNWIND_DEBUG_LOG("__unw_add_dynamic_fde: bad fde: %s", message); } } /// IPI: for __deregister_frame() void __unw_remove_dynamic_fde(unw_word_t fde) { // fde is own mh_group DwarfFDECache::removeAllIn((LocalAddressSpace::pint_t)fde); } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #endif // !defined(__USING_SJLJ_EXCEPTIONS__) // Add logging hooks in Debug builds only #ifndef NDEBUG #include _LIBUNWIND_HIDDEN bool logAPIs() { // do manual lock to avoid use of _cxa_guard_acquire or initializers static bool checked = false; static bool log = false; if (!checked) { log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); checked = true; } return log; } _LIBUNWIND_HIDDEN bool logUnwinding() { // do manual lock to avoid use of _cxa_guard_acquire or initializers static bool checked = false; static bool log = false; if (!checked) { log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); checked = true; } return log; } _LIBUNWIND_HIDDEN bool logDWARF() { // do manual lock to avoid use of _cxa_guard_acquire or initializers static bool checked = false; static bool log = false; if (!checked) { log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL); checked = true; } return log; } #endif // NDEBUG