Index: stable/11/contrib/llvm/projects/libunwind/include/libunwind.h =================================================================== --- stable/11/contrib/llvm/projects/libunwind/include/libunwind.h (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/include/libunwind.h (revision 312447) @@ -1,607 +1,607 @@ //===---------------------------- libunwind.h -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // -// Compatible with libuwind API documented at: +// 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__ #include #ifdef __arm__ #define LIBUNWIND_AVAIL __attribute__((unavailable)) #else #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0) #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 */ }; 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; #if _LIBUNWIND_ARM_EHABI typedef uint32_t unw_word_t; typedef uint64_t unw_fpreg_t; #else typedef uint64_t unw_word_t; 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 UNW_REMOTE /* * Mac OS X "remote" API for unwinding other processes on same machine * */ extern unw_addr_space_t unw_create_addr_space_for_task(task_t); extern void unw_destroy_addr_space(unw_addr_space_t); extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *); #endif /* UNW_REMOTE */ /* - * traditional libuwind "remote" API + * traditional libunwind "remote" API * NOT IMPLEMENTED on Mac OS X * * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, * thread_t*); * extern unw_accessors_t unw_get_accessors(unw_addr_space_t); * extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int); * extern void unw_flush_cache(unw_addr_space_t, unw_word_t, * unw_word_t); * extern int unw_set_caching_policy(unw_addr_space_t, * unw_caching_policy_t); * extern void _U_dyn_register(unw_dyn_info_t*); * extern void _U_dyn_cancel(unw_dyn_info_t*); */ #ifdef __cplusplus } #endif // 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_ESP = 4, UNW_X86_EBP = 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 }; // 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 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_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, }; // 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, }; #endif Index: stable/11/contrib/llvm/projects/libunwind/src/AddressSpace.hpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/AddressSpace.hpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/AddressSpace.hpp (revision 312447) @@ -1,599 +1,599 @@ //===------------------------- AddressSpace.hpp ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Abstracts accessing local vs remote address spaces. // //===----------------------------------------------------------------------===// #ifndef __ADDRESSSPACE_HPP__ #define __ADDRESSSPACE_HPP__ #include #include #include #include #ifndef _LIBUNWIND_IS_BAREMETAL #include #endif #ifdef __APPLE__ #include namespace libunwind { bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); } #endif #include "libunwind.h" #include "config.h" #include "dwarf2.h" #include "Registers.hpp" #if _LIBUNWIND_ARM_EHABI #if defined(__FreeBSD__) || defined(__NetBSD__) #include typedef void *_Unwind_Ptr; #elif defined(__linux__) typedef long unsigned int *_Unwind_Ptr; extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len); // Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system. #define dl_unwind_find_exidx __gnu_Unwind_Find_exidx #elif !defined(_LIBUNWIND_IS_BAREMETAL) #include #else // !defined(_LIBUNWIND_IS_BAREMETAL) // When statically linked on bare-metal, the symbols for the EH table are looked // up without going through the dynamic loader. struct EHTEntry { uint32_t functionOffset; uint32_t unwindOpcodes; }; extern EHTEntry __exidx_start; extern EHTEntry __exidx_end; #endif // !defined(_LIBUNWIND_IS_BAREMETAL) #endif // _LIBUNWIND_ARM_EHABI #if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__) || \ defined(__NetBSD__) #if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX #include // Macro for machine-independent access to the ELF program headers. This // macro is not available on some systems (e.g., FreeBSD). On these // systems the data structures are just called Elf_XXX. Define ElfW() // locally. #if !defined(ElfW) #define ElfW(type) Elf_##type #endif #include "EHHeaderParser.hpp" #endif #endif namespace libunwind { /// Used by findUnwindSections() to return info about needed sections. struct UnwindInfoSections { #if _LIBUNWIND_SUPPORT_DWARF_UNWIND || _LIBUNWIND_SUPPORT_DWARF_INDEX || \ _LIBUNWIND_SUPPORT_COMPACT_UNWIND // No dso_base for ARM EHABI. uintptr_t dso_base; #endif #if _LIBUNWIND_SUPPORT_DWARF_UNWIND uintptr_t dwarf_section; uintptr_t dwarf_section_length; #endif #if _LIBUNWIND_SUPPORT_DWARF_INDEX uintptr_t dwarf_index_section; uintptr_t dwarf_index_section_length; #endif #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND uintptr_t compact_unwind_section; uintptr_t compact_unwind_section_length; #endif #if _LIBUNWIND_ARM_EHABI uintptr_t arm_section; uintptr_t arm_section_length; #endif }; /// LocalAddressSpace is used as a template parameter to UnwindCursor when /// unwinding a thread in the same process. The wrappers compile away, /// making local unwinds fast. class __attribute__((visibility("hidden"))) LocalAddressSpace { public: #ifdef __LP64__ typedef uint64_t pint_t; typedef int64_t sint_t; #else typedef uint32_t pint_t; typedef int32_t sint_t; #endif uint8_t get8(pint_t addr) { uint8_t val; memcpy(&val, (void *)addr, sizeof(val)); return val; } uint16_t get16(pint_t addr) { uint16_t val; memcpy(&val, (void *)addr, sizeof(val)); return val; } uint32_t get32(pint_t addr) { uint32_t val; memcpy(&val, (void *)addr, sizeof(val)); return val; } uint64_t get64(pint_t addr) { uint64_t val; memcpy(&val, (void *)addr, sizeof(val)); return val; } double getDouble(pint_t addr) { double val; memcpy(&val, (void *)addr, sizeof(val)); return val; } v128 getVector(pint_t addr) { v128 val; memcpy(&val, (void *)addr, sizeof(val)); return val; } uintptr_t getP(pint_t addr); static uint64_t getULEB128(pint_t &addr, pint_t end); static int64_t getSLEB128(pint_t &addr, pint_t end); pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase = 0); bool findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset); bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); bool findOtherFDE(pint_t targetAddr, pint_t &fde); static LocalAddressSpace sThisAddressSpace; }; inline uintptr_t LocalAddressSpace::getP(pint_t addr) { #ifdef __LP64__ return get64(addr); #else return get32(addr); #endif } /// Read a ULEB128 into a 64-bit word. inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { const uint8_t *p = (uint8_t *)addr; const uint8_t *pend = (uint8_t *)end; uint64_t result = 0; int bit = 0; do { uint64_t b; if (p == pend) _LIBUNWIND_ABORT("truncated uleb128 expression"); b = *p & 0x7f; if (bit >= 64 || b << bit >> bit != b) { _LIBUNWIND_ABORT("malformed uleb128 expression"); } else { result |= b << bit; bit += 7; } } while (*p++ >= 0x80); addr = (pint_t) p; return result; } /// Read a SLEB128 into a 64-bit word. inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { const uint8_t *p = (uint8_t *)addr; const uint8_t *pend = (uint8_t *)end; int64_t result = 0; int bit = 0; uint8_t byte; do { if (p == pend) _LIBUNWIND_ABORT("truncated sleb128 expression"); byte = *p++; result |= ((byte & 0x7f) << bit); bit += 7; } while (byte & 0x80); // sign extend negative numbers if ((byte & 0x40) != 0) result |= (-1LL) << bit; addr = (pint_t) p; return result; } inline LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase) { pint_t startAddr = addr; const uint8_t *p = (uint8_t *)addr; pint_t result; // first get value switch (encoding & 0x0F) { case DW_EH_PE_ptr: result = getP(addr); p += sizeof(pint_t); addr = (pint_t) p; break; case DW_EH_PE_uleb128: result = (pint_t)getULEB128(addr, end); break; case DW_EH_PE_udata2: result = get16(addr); p += 2; addr = (pint_t) p; break; case DW_EH_PE_udata4: result = get32(addr); p += 4; addr = (pint_t) p; break; case DW_EH_PE_udata8: result = (pint_t)get64(addr); p += 8; addr = (pint_t) p; break; case DW_EH_PE_sleb128: result = (pint_t)getSLEB128(addr, end); break; case DW_EH_PE_sdata2: // Sign extend from signed 16-bit value. result = (pint_t)(int16_t)get16(addr); p += 2; addr = (pint_t) p; break; case DW_EH_PE_sdata4: // Sign extend from signed 32-bit value. result = (pint_t)(int32_t)get32(addr); p += 4; addr = (pint_t) p; break; case DW_EH_PE_sdata8: result = (pint_t)get64(addr); p += 8; addr = (pint_t) p; break; default: _LIBUNWIND_ABORT("unknown pointer encoding"); } // then add relative offset switch (encoding & 0x70) { case DW_EH_PE_absptr: // do nothing break; case DW_EH_PE_pcrel: result += startAddr; break; case DW_EH_PE_textrel: _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported"); break; case DW_EH_PE_datarel: // DW_EH_PE_datarel is only valid in a few places, so the parameter has a // default value of 0, and we abort in the event that someone calls this // function with a datarelBase of 0 and DW_EH_PE_datarel encoding. if (datarelBase == 0) _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0"); result += datarelBase; break; case DW_EH_PE_funcrel: _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported"); break; case DW_EH_PE_aligned: _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported"); break; default: _LIBUNWIND_ABORT("unknown pointer encoding"); break; } if (encoding & DW_EH_PE_indirect) result = getP(result); return result; } #ifdef __APPLE__ struct dyld_unwind_sections { const struct mach_header* mh; const void* dwarf_section; uintptr_t dwarf_section_length; const void* compact_unwind_section; uintptr_t compact_unwind_section_length; }; #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) // In 10.7.0 or later, libSystem.dylib implements this function. extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); #else // In 10.6.x and earlier, we need to implement this functionality. static inline bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info) { // Find mach-o image containing address. Dl_info dlinfo; if (!dladdr(addr, &dlinfo)) return false; const mach_header *mh = (const mach_header *)dlinfo.dli_saddr; // Find dwarf unwind section in that image. unsigned long size; const uint8_t *p = getsectiondata(mh, "__TEXT", "__eh_frame", &size); if (!p) return false; // Fill in return struct. info->mh = mh; info->dwarf_section = p; info->dwarf_section_length = size; info->compact_unwind_section = 0; info->compact_unwind_section_length = 0; return true; } #endif #endif inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ dyld_unwind_sections dyldInfo; if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { info.dso_base = (uintptr_t)dyldInfo.mh; #if _LIBUNWIND_SUPPORT_DWARF_UNWIND info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; info.dwarf_section_length = dyldInfo.dwarf_section_length; #endif info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; return true; } #elif _LIBUNWIND_ARM_EHABI #ifdef _LIBUNWIND_IS_BAREMETAL // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); #else int length = 0; info.arm_section = (uintptr_t) dl_unwind_find_exidx( (_Unwind_Ptr) targetAddr, &length); info.arm_section_length = (uintptr_t)length; #endif - _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x\n", + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x", info.arm_section, info.arm_section_length); if (info.arm_section && info.arm_section_length) return true; #elif _LIBUNWIND_SUPPORT_DWARF_UNWIND #if _LIBUNWIND_SUPPORT_DWARF_INDEX struct dl_iterate_cb_data { LocalAddressSpace *addressSpace; UnwindInfoSections *sects; uintptr_t targetAddr; }; dl_iterate_cb_data cb_data = {this, &info, targetAddr}; int found = dl_iterate_phdr( [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { auto cbdata = static_cast(data); size_t object_length; bool found_obj = false; bool found_hdr = false; assert(cbdata); assert(cbdata->sects); if (cbdata->targetAddr < pinfo->dlpi_addr) { return false; } #if !defined(Elf_Half) typedef ElfW(Half) Elf_Half; #endif #if !defined(Elf_Phdr) typedef ElfW(Phdr) Elf_Phdr; #endif for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; uintptr_t end = begin + phdr->p_memsz; if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { cbdata->sects->dso_base = begin; object_length = phdr->p_memsz; found_obj = true; } } else if (phdr->p_type == PT_GNU_EH_FRAME) { EHHeaderParser::EHHeaderInfo hdrInfo; uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; EHHeaderParser::decodeEHHdr( *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, hdrInfo); cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; found_hdr = true; } } if (found_obj && found_hdr) { cbdata->sects->dwarf_section_length = object_length; return true; } else { return false; } }, &cb_data); return static_cast(found); #else #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." #endif #endif return false; } inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { #ifdef __APPLE__ return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); #else // TO DO: if OS has way to dynamically register FDEs, check that. (void)targetAddr; (void)fde; return false; #endif } inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { #ifndef _LIBUNWIND_IS_BAREMETAL Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { if (dyldInfo.dli_sname != NULL) { snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); *offset = (addr - (pint_t) dyldInfo.dli_saddr); return true; } } #endif return false; } #ifdef UNW_REMOTE /// OtherAddressSpace is used as a template parameter to UnwindCursor when /// unwinding a thread in the another process. The other process can be a /// different endianness and a different pointer size which is handled by /// the P template parameter. template class OtherAddressSpace { public: OtherAddressSpace(task_t task) : fTask(task) {} typedef typename P::uint_t pint_t; uint8_t get8(pint_t addr); uint16_t get16(pint_t addr); uint32_t get32(pint_t addr); uint64_t get64(pint_t addr); pint_t getP(pint_t addr); uint64_t getULEB128(pint_t &addr, pint_t end); int64_t getSLEB128(pint_t &addr, pint_t end); pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase = 0); bool findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset); bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); bool findOtherFDE(pint_t targetAddr, pint_t &fde); private: void *localCopy(pint_t addr); task_t fTask; }; template uint8_t OtherAddressSpace

::get8(pint_t addr) { return *((uint8_t *)localCopy(addr)); } template uint16_t OtherAddressSpace

::get16(pint_t addr) { return P::E::get16(*(uint16_t *)localCopy(addr)); } template uint32_t OtherAddressSpace

::get32(pint_t addr) { return P::E::get32(*(uint32_t *)localCopy(addr)); } template uint64_t OtherAddressSpace

::get64(pint_t addr) { return P::E::get64(*(uint64_t *)localCopy(addr)); } template typename P::uint_t OtherAddressSpace

::getP(pint_t addr) { return P::getP(*(uint64_t *)localCopy(addr)); } template uint64_t OtherAddressSpace

::getULEB128(pint_t &addr, pint_t end) { uintptr_t size = (end - addr); LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); LocalAddressSpace::pint_t sladdr = laddr; uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size); addr += (laddr - sladdr); return result; } template int64_t OtherAddressSpace

::getSLEB128(pint_t &addr, pint_t end) { uintptr_t size = (end - addr); LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); LocalAddressSpace::pint_t sladdr = laddr; uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size); addr += (laddr - sladdr); return result; } template void *OtherAddressSpace

::localCopy(pint_t addr) { // FIX ME } template bool OtherAddressSpace

::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { // FIX ME } /// unw_addr_space is the base class that abstract unw_addr_space_t type in /// libunwind.h points to. struct unw_addr_space { cpu_type_t cpuType; task_t taskPort; }; /// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points /// to when examining /// a 32-bit intel process. struct unw_addr_space_i386 : public unw_addr_space { unw_addr_space_i386(task_t task) : oas(task) {} OtherAddressSpace > oas; }; /// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t /// points to when examining /// a 64-bit intel process. struct unw_addr_space_x86_64 : public unw_addr_space { unw_addr_space_x86_64(task_t task) : oas(task) {} OtherAddressSpace > oas; }; /// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points /// to when examining /// a 32-bit PowerPC process. struct unw_addr_space_ppc : public unw_addr_space { unw_addr_space_ppc(task_t task) : oas(task) {} OtherAddressSpace > oas; }; #endif // UNW_REMOTE } // namespace libunwind #endif // __ADDRESSSPACE_HPP__ Index: stable/11/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp (revision 312447) @@ -1,699 +1,699 @@ //===-------------------------- CompactUnwinder.hpp -----------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Does runtime stack unwinding using compact unwind encodings. // //===----------------------------------------------------------------------===// #ifndef __COMPACT_UNWINDER_HPP__ #define __COMPACT_UNWINDER_HPP__ #include #include #include #include #include "AddressSpace.hpp" #include "Registers.hpp" #define EXTRACT_BITS(value, mask) \ ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) namespace libunwind { #if defined(_LIBUNWIND_TARGET_I386) /// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_x86 register set template class CompactUnwinder_x86 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t info, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters); private: typename A::pint_t pint_t; static void frameUnwind(A &addressSpace, Registers_x86 ®isters); static void framelessUnwind(A &addressSpace, typename A::pint_t returnAddressLocation, Registers_x86 ®isters); static int stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); }; template int CompactUnwinder_x86::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters) { switch (compactEncoding & UNWIND_X86_MODE_MASK) { case UNWIND_X86_MODE_EBP_FRAME: return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, addressSpace, registers); case UNWIND_X86_MODE_STACK_IMMD: return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false); case UNWIND_X86_MODE_STACK_IND: return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true); } _LIBUNWIND_ABORT("invalid compact unwind encoding"); } template int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( compact_unwind_encoding_t compactEncoding, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS); uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset; for (int i = 0; i < 5; ++i) { switch (savedRegistersLocations & 0x7) { case UNWIND_X86_REG_NONE: // no register saved in this slot break; case UNWIND_X86_REG_EBX: registers.setEBX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ECX: registers.setECX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDX: registers.setEDX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDI: registers.setEDI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ESI: registers.setESI(addressSpace.get32(savedRegisters)); break; default: (void)functionStart; _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for " - "function starting at 0x%X\n", + "function starting at 0x%X", compactEncoding, functionStart); _LIBUNWIND_ABORT("invalid compact unwind encoding"); } savedRegisters += 4; savedRegistersLocations = (savedRegistersLocations >> 3); } frameUnwind(addressSpace, registers); return UNW_STEP_SUCCESS; } template int CompactUnwinder_x86::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint32_t functionStart, A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); uint32_t stackSize = stackSizeEncoded * 4; if (indirectStackSize) { // stack size is encoded in subl $xxx,%esp instruction uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); stackSize = subl + 4 * stackAdjust; } // decompress permutation uint32_t permunreg[6]; switch (regCount) { case 6: permunreg[0] = permutation / 120; permutation -= (permunreg[0] * 120); permunreg[1] = permutation / 24; permutation -= (permunreg[1] * 24); permunreg[2] = permutation / 6; permutation -= (permunreg[2] * 6); permunreg[3] = permutation / 2; permutation -= (permunreg[3] * 2); permunreg[4] = permutation; permunreg[5] = 0; break; case 5: permunreg[0] = permutation / 120; permutation -= (permunreg[0] * 120); permunreg[1] = permutation / 24; permutation -= (permunreg[1] * 24); permunreg[2] = permutation / 6; permutation -= (permunreg[2] * 6); permunreg[3] = permutation / 2; permutation -= (permunreg[3] * 2); permunreg[4] = permutation; break; case 4: permunreg[0] = permutation / 60; permutation -= (permunreg[0] * 60); permunreg[1] = permutation / 12; permutation -= (permunreg[1] * 12); permunreg[2] = permutation / 3; permutation -= (permunreg[2] * 3); permunreg[3] = permutation; break; case 3: permunreg[0] = permutation / 20; permutation -= (permunreg[0] * 20); permunreg[1] = permutation / 4; permutation -= (permunreg[1] * 4); permunreg[2] = permutation; break; case 2: permunreg[0] = permutation / 5; permutation -= (permunreg[0] * 5); permunreg[1] = permutation; break; case 1: permunreg[0] = permutation; break; } // re-number registers back to standard numbers int registersSaved[6]; bool used[7] = { false, false, false, false, false, false, false }; for (uint32_t i = 0; i < regCount; ++i) { uint32_t renum = 0; for (int u = 1; u < 7; ++u) { if (!used[u]) { if (renum == permunreg[i]) { registersSaved[i] = u; used[u] = true; break; } ++renum; } } } uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount; for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_REG_EBX: registers.setEBX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ECX: registers.setECX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDX: registers.setEDX(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EDI: registers.setEDI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_ESI: registers.setESI(addressSpace.get32(savedRegisters)); break; case UNWIND_X86_REG_EBP: registers.setEBP(addressSpace.get32(savedRegisters)); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " - "function starting at 0x%X\n", + "function starting at 0x%X", encoding, functionStart); _LIBUNWIND_ABORT("invalid compact unwind encoding"); } savedRegisters += 4; } framelessUnwind(addressSpace, savedRegisters, registers); return UNW_STEP_SUCCESS; } template void CompactUnwinder_x86::frameUnwind(A &addressSpace, Registers_x86 ®isters) { typename A::pint_t bp = registers.getEBP(); // ebp points to old ebp registers.setEBP(addressSpace.get32(bp)); // old esp is ebp less saved ebp and return address registers.setSP((uint32_t)bp + 8); // pop return address into eip registers.setIP(addressSpace.get32(bp + 4)); } template void CompactUnwinder_x86::framelessUnwind( A &addressSpace, typename A::pint_t returnAddressLocation, Registers_x86 ®isters) { // return address is on stack after last saved register registers.setIP(addressSpace.get32(returnAddressLocation)); // old esp is before return address registers.setSP((uint32_t)returnAddressLocation + 4); } #endif // _LIBUNWIND_TARGET_I386 #if defined(_LIBUNWIND_TARGET_X86_64) /// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_x86_64 register set template class CompactUnwinder_x86_64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters); private: typename A::pint_t pint_t; static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, Registers_x86_64 ®isters); static int stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); }; template int CompactUnwinder_x86_64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters) { switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { case UNWIND_X86_64_MODE_RBP_FRAME: return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, addressSpace, registers); case UNWIND_X86_64_MODE_STACK_IMMD: return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, false); case UNWIND_X86_64_MODE_STACK_IND: return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers, true); } _LIBUNWIND_ABORT("invalid compact unwind encoding"); } template int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters) { uint32_t savedRegistersOffset = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); uint32_t savedRegistersLocations = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset; for (int i = 0; i < 5; ++i) { switch (savedRegistersLocations & 0x7) { case UNWIND_X86_64_REG_NONE: // no register saved in this slot break; case UNWIND_X86_64_REG_RBX: registers.setRBX(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R12: registers.setR12(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R13: registers.setR13(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R14: registers.setR14(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R15: registers.setR15(addressSpace.get64(savedRegisters)); break; default: (void)functionStart; _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for " - "function starting at 0x%llX\n", + "function starting at 0x%llX", compactEncoding, functionStart); _LIBUNWIND_ABORT("invalid compact unwind encoding"); } savedRegisters += 8; savedRegistersLocations = (savedRegistersLocations >> 3); } frameUnwind(addressSpace, registers); return UNW_STEP_SUCCESS; } template int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize) { uint32_t stackSizeEncoded = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); uint32_t stackAdjust = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); uint32_t regCount = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); uint32_t permutation = EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); uint32_t stackSize = stackSizeEncoded * 8; if (indirectStackSize) { // stack size is encoded in subl $xxx,%esp instruction uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); stackSize = subl + 8 * stackAdjust; } // decompress permutation uint32_t permunreg[6]; switch (regCount) { case 6: permunreg[0] = permutation / 120; permutation -= (permunreg[0] * 120); permunreg[1] = permutation / 24; permutation -= (permunreg[1] * 24); permunreg[2] = permutation / 6; permutation -= (permunreg[2] * 6); permunreg[3] = permutation / 2; permutation -= (permunreg[3] * 2); permunreg[4] = permutation; permunreg[5] = 0; break; case 5: permunreg[0] = permutation / 120; permutation -= (permunreg[0] * 120); permunreg[1] = permutation / 24; permutation -= (permunreg[1] * 24); permunreg[2] = permutation / 6; permutation -= (permunreg[2] * 6); permunreg[3] = permutation / 2; permutation -= (permunreg[3] * 2); permunreg[4] = permutation; break; case 4: permunreg[0] = permutation / 60; permutation -= (permunreg[0] * 60); permunreg[1] = permutation / 12; permutation -= (permunreg[1] * 12); permunreg[2] = permutation / 3; permutation -= (permunreg[2] * 3); permunreg[3] = permutation; break; case 3: permunreg[0] = permutation / 20; permutation -= (permunreg[0] * 20); permunreg[1] = permutation / 4; permutation -= (permunreg[1] * 4); permunreg[2] = permutation; break; case 2: permunreg[0] = permutation / 5; permutation -= (permunreg[0] * 5); permunreg[1] = permutation; break; case 1: permunreg[0] = permutation; break; } // re-number registers back to standard numbers int registersSaved[6]; bool used[7] = { false, false, false, false, false, false, false }; for (uint32_t i = 0; i < regCount; ++i) { uint32_t renum = 0; for (int u = 1; u < 7; ++u) { if (!used[u]) { if (renum == permunreg[i]) { registersSaved[i] = u; used[u] = true; break; } ++renum; } } } uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount; for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_64_REG_RBX: registers.setRBX(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R12: registers.setR12(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R13: registers.setR13(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R14: registers.setR14(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_R15: registers.setR15(addressSpace.get64(savedRegisters)); break; case UNWIND_X86_64_REG_RBP: registers.setRBP(addressSpace.get64(savedRegisters)); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " - "function starting at 0x%llX\n", + "function starting at 0x%llX", encoding, functionStart); _LIBUNWIND_ABORT("invalid compact unwind encoding"); } savedRegisters += 8; } framelessUnwind(addressSpace, savedRegisters, registers); return UNW_STEP_SUCCESS; } template void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, Registers_x86_64 ®isters) { uint64_t rbp = registers.getRBP(); // ebp points to old ebp registers.setRBP(addressSpace.get64(rbp)); // old esp is ebp less saved ebp and return address registers.setSP(rbp + 16); // pop return address into eip registers.setIP(addressSpace.get64(rbp + 8)); } template void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, Registers_x86_64 ®isters) { // return address is on stack after last saved register registers.setIP(addressSpace.get64(returnAddressLocation)); // old esp is before return address registers.setSP(returnAddressLocation + 8); } #endif // _LIBUNWIND_TARGET_X86_64 #if defined(_LIBUNWIND_TARGET_AARCH64) /// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka /// unwind) by modifying a Registers_arm64 register set template class CompactUnwinder_arm64 { public: static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_arm64 ®isters); private: typename A::pint_t pint_t; static int stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_arm64 ®isters); static int stepWithCompactEncodingFrameless( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_arm64 ®isters); }; template int CompactUnwinder_arm64::stepWithCompactEncoding( compact_unwind_encoding_t compactEncoding, uint64_t functionStart, A &addressSpace, Registers_arm64 ®isters) { switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: return stepWithCompactEncodingFrame(compactEncoding, functionStart, addressSpace, registers); case UNWIND_ARM64_MODE_FRAMELESS: return stepWithCompactEncodingFrameless(compactEncoding, functionStart, addressSpace, registers); } _LIBUNWIND_ABORT("invalid compact unwind encoding"); } template int CompactUnwinder_arm64::stepWithCompactEncodingFrameless( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, Registers_arm64 ®isters) { uint32_t stackSize = 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); uint64_t savedRegisterLoc = registers.getSP() + stackSize; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { registers.setFloatRegister(UNW_ARM64_D8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { registers.setFloatRegister(UNW_ARM64_D10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { registers.setFloatRegister(UNW_ARM64_D12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { registers.setFloatRegister(UNW_ARM64_D14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } // subtract stack size off of sp registers.setSP(savedRegisterLoc); // set pc to be value in lr registers.setIP(registers.getRegister(UNW_ARM64_LR)); return UNW_STEP_SUCCESS; } template int CompactUnwinder_arm64::stepWithCompactEncodingFrame( compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, Registers_arm64 ®isters) { uint64_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { registers.setFloatRegister(UNW_ARM64_D8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { registers.setFloatRegister(UNW_ARM64_D10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { registers.setFloatRegister(UNW_ARM64_D12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { registers.setFloatRegister(UNW_ARM64_D14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } uint64_t fp = registers.getFP(); // fp points to old fp registers.setFP(addressSpace.get64(fp)); // old sp is fp less saved fp and lr registers.setSP(fp + 16); // pop return address into pc registers.setIP(addressSpace.get64(fp + 8)); return UNW_STEP_SUCCESS; } #endif // _LIBUNWIND_TARGET_AARCH64 } // namespace libunwind #endif // __COMPACT_UNWINDER_HPP__ Index: stable/11/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp (revision 312447) @@ -1,161 +1,161 @@ //===------------------------- EHHeaderParser.hpp -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Parses ELF .eh_frame_hdr sections. // //===----------------------------------------------------------------------===// #ifndef __EHHEADERPARSER_HPP__ #define __EHHEADERPARSER_HPP__ #include "libunwind.h" #include "AddressSpace.hpp" #include "DwarfParser.hpp" namespace libunwind { /// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section. /// /// See DWARF spec for details: /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html /// template class EHHeaderParser { public: typedef typename A::pint_t pint_t; /// Information encoded in the EH frame header. struct EHHeaderInfo { pint_t eh_frame_ptr; size_t fde_count; pint_t table; uint8_t table_enc; }; static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo); static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo); private: static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd, uint8_t tableEnc, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo); static size_t getTableEntrySize(uint8_t tableEnc); }; template void EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { pint_t p = ehHdrStart; uint8_t version = addressSpace.get8(p++); if (version != 1) _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version"); uint8_t eh_frame_ptr_enc = addressSpace.get8(p++); uint8_t fde_count_enc = addressSpace.get8(p++); ehHdrInfo.table_enc = addressSpace.get8(p++); ehHdrInfo.eh_frame_ptr = addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart); ehHdrInfo.fde_count = addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); ehHdrInfo.table = p; } template bool EHHeaderParser::decodeTableEntry( A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd, uint8_t tableEnc, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo) { // Have to decode the whole FDE for the PC range anyway, so just throw away // the PC start. addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); pint_t fde = addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart); const char *message = CFI_Parser::decodeFDE(addressSpace, fde, fdeInfo, cieInfo); if (message != NULL) { - _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s\n", + _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s", message); return false; } return true; } template bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser::FDE_Info *fdeInfo, typename CFI_Parser::CIE_Info *cieInfo) { pint_t ehHdrEnd = ehHdrStart + sectionLength; EHHeaderParser::EHHeaderInfo hdrInfo; EHHeaderParser::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo); size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); pint_t tableEntry; size_t low = 0; for (size_t len = hdrInfo.fde_count; len > 1;) { size_t mid = low + (len / 2); tableEntry = hdrInfo.table + mid * tableEntrySize; pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd, hdrInfo.table_enc, ehHdrStart); if (start == pc) { low = mid; break; } else if (start < pc) { low = mid; len -= (len / 2); } else { len /= 2; } } tableEntry = hdrInfo.table + low * tableEntrySize; if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd, hdrInfo.table_enc, fdeInfo, cieInfo)) { if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd) return true; } return false; } template size_t EHHeaderParser::getTableEntrySize(uint8_t tableEnc) { switch (tableEnc & 0x0f) { case DW_EH_PE_sdata2: case DW_EH_PE_udata2: return 4; case DW_EH_PE_sdata4: case DW_EH_PE_udata4: return 8; case DW_EH_PE_sdata8: case DW_EH_PE_udata8: return 16; case DW_EH_PE_sleb128: case DW_EH_PE_uleb128: _LIBUNWIND_ABORT("Can't binary search on variable length encoded data."); case DW_EH_PE_omit: return 0; default: _LIBUNWIND_ABORT("Unknown DWARF encoding for search table."); } } } #endif Index: stable/11/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp (revision 312447) @@ -1,977 +1,977 @@ //===--------------------------- Unwind-EHABI.cpp -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Implements ARM zero-cost C++ exceptions // //===----------------------------------------------------------------------===// #include "Unwind-EHABI.h" #if _LIBUNWIND_ARM_EHABI #include #include #include #include #include #include #include "config.h" #include "libunwind.h" #include "libunwind_ext.h" #include "unwind.h" namespace { // Strange order: take words in order, but inside word, take from most to least // signinficant byte. uint8_t getByte(const uint32_t* data, size_t offset) { const uint8_t* byteData = reinterpret_cast(data); return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; } const char* getNextWord(const char* data, uint32_t* out) { *out = *reinterpret_cast(data); return data + 4; } const char* getNextNibble(const char* data, uint32_t* out) { *out = *reinterpret_cast(data); return data + 2; } struct Descriptor { // See # 9.2 typedef enum { SU16 = 0, // Short descriptor, 16-bit entries LU16 = 1, // Long descriptor, 16-bit entries LU32 = 3, // Long descriptor, 32-bit entries RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7, RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11, RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15 } Format; // See # 9.2 typedef enum { CLEANUP = 0x0, FUNC = 0x1, CATCH = 0x2, INVALID = 0x4 } Kind; }; _Unwind_Reason_Code ProcessDescriptors( _Unwind_State state, _Unwind_Control_Block* ucbp, struct _Unwind_Context* context, Descriptor::Format format, const char* descriptorStart, uint32_t flags) { // EHT is inlined in the index using compact form. No descriptors. #5 if (flags & 0x1) return _URC_CONTINUE_UNWIND; // TODO: We should check the state here, and determine whether we need to // perform phase1 or phase2 unwinding. (void)state; const char* descriptor = descriptorStart; uint32_t descriptorWord; getNextWord(descriptor, &descriptorWord); while (descriptorWord) { // Read descriptor based on # 9.2. uint32_t length; uint32_t offset; switch (format) { case Descriptor::LU32: descriptor = getNextWord(descriptor, &length); descriptor = getNextWord(descriptor, &offset); case Descriptor::LU16: descriptor = getNextNibble(descriptor, &length); descriptor = getNextNibble(descriptor, &offset); default: assert(false); return _URC_FAILURE; } // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value. Descriptor::Kind kind = static_cast((length & 0x1) | ((offset & 0x1) << 1)); // Clear off flag from last bit. length &= ~1u; offset &= ~1u; uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset; uintptr_t scopeEnd = scopeStart + length; uintptr_t pc = _Unwind_GetIP(context); bool isInScope = (scopeStart <= pc) && (pc < scopeEnd); switch (kind) { case Descriptor::CLEANUP: { // TODO(ajwong): Handle cleanup descriptors. break; } case Descriptor::FUNC: { // TODO(ajwong): Handle function descriptors. break; } case Descriptor::CATCH: { // Catch descriptors require gobbling one more word. uint32_t landing_pad; descriptor = getNextWord(descriptor, &landing_pad); if (isInScope) { // TODO(ajwong): This is only phase1 compatible logic. Implement // phase2. landing_pad = signExtendPrel31(landing_pad & ~0x80000000); if (landing_pad == 0xffffffff) { return _URC_HANDLER_FOUND; } else if (landing_pad == 0xfffffffe) { return _URC_FAILURE; } else { /* bool is_reference_type = landing_pad & 0x80000000; void* matched_object; if (__cxxabiv1::__cxa_type_match( ucbp, reinterpret_cast(landing_pad), is_reference_type, &matched_object) != __cxxabiv1::ctm_failed) return _URC_HANDLER_FOUND; */ _LIBUNWIND_ABORT("Type matching not implemented"); } } break; } default: _LIBUNWIND_ABORT("Invalid descriptor kind found."); } getNextWord(descriptor, &descriptorWord); } return _URC_CONTINUE_UNWIND; } static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, _Unwind_Control_Block* ucbp, struct _Unwind_Context* context) { // Read the compact model EHT entry's header # 6.3 const uint32_t* unwindingData = ucbp->pr_cache.ehtp; assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry"); Descriptor::Format format = static_cast((*unwindingData & 0x0f000000) >> 24); const char *lsda = reinterpret_cast(_Unwind_GetLanguageSpecificData(context)); // Handle descriptors before unwinding so they are processed in the context // of the correct stack frame. _Unwind_Reason_Code result = ProcessDescriptors(state, ucbp, context, format, lsda, ucbp->pr_cache.additional); if (result != _URC_CONTINUE_UNWIND) return result; if (unw_step(reinterpret_cast(context)) != UNW_STEP_SUCCESS) return _URC_FAILURE; return _URC_CONTINUE_UNWIND; } // Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE / // _UVRSD_UINT32. uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) { return ((1U << (count_minus_one + 1)) - 1) << start; } // Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP / // _UVRSD_DOUBLE. uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) { return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1); } } // end anonymous namespace /** * Decodes an EHT entry. * * @param data Pointer to EHT. * @param[out] off Offset from return value (in bytes) to begin interpretation. * @param[out] len Number of bytes in unwind code. * @return Pointer to beginning of unwind code. */ extern "C" const uint32_t* decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { if ((*data & 0x80000000) == 0) { // 6.2: Generic Model // // EHT entry is a prel31 pointing to the PR, followed by data understood // only by the personality routine. Fortunately, all existing assembler // implementations, including GNU assembler, LLVM integrated assembler, // and ARM assembler, assume that the unwind opcodes come after the // personality rountine address. *off = 1; // First byte is size data. *len = (((data[1] >> 24) & 0xff) + 1) * 4; data++; // Skip the first word, which is the prel31 offset. } else { // 6.3: ARM Compact Model // // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded // by format: Descriptor::Format format = static_cast((*data & 0x0f000000) >> 24); switch (format) { case Descriptor::SU16: *len = 4; *off = 1; break; case Descriptor::LU16: case Descriptor::LU32: *len = 4 + 4 * ((*data & 0x00ff0000) >> 16); *off = 2; break; default: return nullptr; } } return data; } _Unwind_Reason_Code _Unwind_VRS_Interpret( _Unwind_Context* context, const uint32_t* data, size_t offset, size_t len) { bool wrotePC = false; bool finish = false; while (offset < len && !finish) { uint8_t byte = getByte(data, offset++); if ((byte & 0x80) == 0) { uint32_t sp; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); if (byte & 0x40) sp -= (((uint32_t)byte & 0x3f) << 2) + 4; else sp += ((uint32_t)byte << 2) + 4; _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } else { switch (byte & 0xf0) { case 0x80: { if (offset >= len) return _URC_FAILURE; uint32_t registers = (((uint32_t)byte & 0x0f) << 12) | (((uint32_t)getByte(data, offset++)) << 4); if (!registers) return _URC_FAILURE; if (registers & (1 << 15)) wrotePC = true; _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); break; } case 0x90: { uint8_t reg = byte & 0x0f; if (reg == 13 || reg == 15) return _URC_FAILURE; uint32_t sp; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, _UVRSD_UINT32, &sp); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); break; } case 0xa0: { uint32_t registers = RegisterMask(4, byte & 0x07); if (byte & 0x08) registers |= 1 << 14; _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); break; } case 0xb0: { switch (byte) { case 0xb0: finish = true; break; case 0xb1: { if (offset >= len) return _URC_FAILURE; uint8_t registers = getByte(data, offset++); if (registers & 0xf0 || !registers) return _URC_FAILURE; _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); break; } case 0xb2: { uint32_t addend = 0; uint32_t shift = 0; // This decodes a uleb128 value. while (true) { if (offset >= len) return _URC_FAILURE; uint32_t v = getByte(data, offset++); addend |= (v & 0x7f) << shift; if ((v & 0x80) == 0) break; shift += 7; } uint32_t sp; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); sp += 0x204 + (addend << 2); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); break; } case 0xb3: { uint8_t v = getByte(data, offset++); _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(static_cast(v >> 4), v & 0x0f), _UVRSD_VFPX); break; } case 0xb4: case 0xb5: case 0xb6: case 0xb7: return _URC_FAILURE; default: _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x07), _UVRSD_VFPX); break; } break; } case 0xc0: { switch (byte) { case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: _Unwind_VRS_Pop(context, _UVRSC_WMMXD, RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE); break; case 0xc6: { uint8_t v = getByte(data, offset++); uint8_t start = static_cast(v >> 4); uint8_t count_minus_one = v & 0xf; if (start + count_minus_one >= 16) return _URC_FAILURE; _Unwind_VRS_Pop(context, _UVRSC_WMMXD, RegisterRange(start, count_minus_one), _UVRSD_DOUBLE); break; } case 0xc7: { uint8_t v = getByte(data, offset++); if (!v || v & 0xf0) return _URC_FAILURE; _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE); break; } case 0xc8: case 0xc9: { uint8_t v = getByte(data, offset++); uint8_t start = static_cast(((byte == 0xc8) ? 16 : 0) + (v >> 4)); uint8_t count_minus_one = v & 0xf; if (start + count_minus_one >= 32) return _URC_FAILURE; _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(start, count_minus_one), _UVRSD_DOUBLE); break; } default: return _URC_FAILURE; } break; } case 0xd0: { if (byte & 0x08) return _URC_FAILURE; _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7), _UVRSD_DOUBLE); break; } default: return _URC_FAILURE; } } } if (!wrotePC) { uint32_t lr; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); } return _URC_CONTINUE_UNWIND; } extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0( _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context) { return unwindOneFrame(state, ucbp, context); } extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1( _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context) { return unwindOneFrame(state, ucbp, context); } extern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2( _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context) { return unwindOneFrame(state, ucbp, context); } static _Unwind_Reason_Code unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during // phase 1 and then restoring it to the "primary VRS" for phase 2. The // effect is phase 2 doesn't see any of the VRS manipulations from phase 1. // In this implementation, the phases don't share the VRS backing store. // Instead, they are passed the original |uc| and they create a new VRS // from scratch thus achieving the same effect. unw_init_local(cursor, uc); // Walk each frame looking for a place to stop. for (bool handlerNotFound = true; handlerNotFound;) { // See if frame has code to run (has personality routine). unw_proc_info_t frameInfo; if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", + "failed => _URC_FATAL_PHASE1_ERROR", static_cast(exception_object)); return _URC_FATAL_PHASE1_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; const char *functionName = functionBuf; unw_word_t offset; if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; unw_word_t pc; unw_get_reg(cursor, UNW_REG_IP, &pc); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, " - "lsda=0x%llX, personality=0x%llX\n", + "lsda=0x%llX, personality=0x%llX", static_cast(exception_object), (long long)pc, (long long)frameInfo.start_ip, functionName, (long long)frameInfo.lsda, (long long)frameInfo.handler); } // If there is a personality routine, ask it if it will want to stop at // this frame. if (frameInfo.handler != 0) { __personality_routine p = (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): calling personality function %p\n", + "unwind_phase1(ex_ojb=%p): calling personality function %p", static_cast(exception_object), reinterpret_cast(reinterpret_cast(p))); struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); exception_object->pr_cache.fnstart = frameInfo.start_ip; exception_object->pr_cache.ehtp = (_Unwind_EHT_Header *)frameInfo.unwind_info; exception_object->pr_cache.additional = frameInfo.flags; _Unwind_Reason_Code personalityResult = (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p " - "additional %x\n", + "additional %x", static_cast(exception_object), personalityResult, exception_object->pr_cache.fnstart, static_cast(exception_object->pr_cache.ehtp), exception_object->pr_cache.additional); switch (personalityResult) { case _URC_HANDLER_FOUND: // found a catch clause or locals that need destructing in this frame // stop search and remember stack pointer at the frame handlerNotFound = false; // p should have initialized barrier_cache. EHABI #7.3.5 _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n", + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", static_cast(exception_object)); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", + "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", static_cast(exception_object)); // continue unwinding break; // EHABI #7.3.3 case _URC_FAILURE: return _URC_FAILURE; default: // something went wrong _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", static_cast(exception_object)); return _URC_FATAL_PHASE1_ERROR; } } } return _URC_NO_REASON; } static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object, bool resume) { // See comment at the start of unwind_phase1 regarding VRS integrity. unw_init_local(cursor, uc); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", static_cast(exception_object)); int frame_count = 0; // Walk each frame until we reach where search phase said to stop. while (true) { - // Ask libuwind to get next frame (skip over first which is + // Ask libunwind to get next frame (skip over first which is // _Unwind_RaiseException or _Unwind_Resume). // // Resume only ever makes sense for 1 frame. _Unwind_State state = resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING; if (resume && frame_count == 1) { // On a resume, first unwind the _Unwind_Resume() frame. The next frame // is now the landing pad for the cleanup from a previous execution of // phase2. To continue unwindingly correctly, replace VRS[15] with the // IP of the frame that the previous run of phase2 installed the context // for. After this, continue unwinding as if normal. // // See #7.4.6 for details. unw_set_reg(cursor, UNW_REG_IP, exception_object->unwinder_cache.reserved2); resume = false; } // Get info about this frame. unw_word_t sp; unw_proc_info_t frameInfo; unw_get_reg(cursor, UNW_REG_SP, &sp); if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE2_ERROR\n", + "failed => _URC_FATAL_PHASE2_ERROR", static_cast(exception_object)); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; const char *functionName = functionBuf; unw_word_t offset; if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, " - "lsda=0x%llX, personality=0x%llX\n", + "lsda=0x%llX, personality=0x%llX", static_cast(exception_object), (long long)frameInfo.start_ip, functionName, (long long)sp, (long long)frameInfo.lsda, (long long)frameInfo.handler); } // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { __personality_routine p = (__personality_routine)(long)(frameInfo.handler); struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); // EHABI #7.2 exception_object->pr_cache.fnstart = frameInfo.start_ip; exception_object->pr_cache.ehtp = (_Unwind_EHT_Header *)frameInfo.unwind_info; exception_object->pr_cache.additional = frameInfo.flags; _Unwind_Reason_Code personalityResult = (*p)(state, exception_object, context); switch (personalityResult) { case _URC_CONTINUE_UNWIND: // Continue unwinding _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", static_cast(exception_object)); // EHABI #7.2 if (sp == exception_object->barrier_cache.sp) { // Phase 1 said we would stop at this frame, but we did not... _LIBUNWIND_ABORT("during phase1 personality function said it would " "stop here, but now in phase2 it did not stop here"); } break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", + "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", static_cast(exception_object)); // Personality routine says to transfer control to landing pad. // We may get control back if landing pad calls _Unwind_Resume(). if (_LIBUNWIND_TRACING_UNWINDING) { unw_word_t pc; unw_get_reg(cursor, UNW_REG_IP, &pc); unw_get_reg(cursor, UNW_REG_SP, &sp); _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " - "user code with ip=0x%llX, sp=0x%llX\n", + "user code with ip=0x%llX, sp=0x%llX", static_cast(exception_object), (long long)pc, (long long)sp); } { // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume // is called back, to find this same frame. unw_word_t pc; unw_get_reg(cursor, UNW_REG_IP, &pc); exception_object->unwinder_cache.reserved2 = (uint32_t)pc; } unw_resume(cursor); // unw_resume() only returns if there was an error. return _URC_FATAL_PHASE2_ERROR; // # EHABI #7.4.3 case _URC_FAILURE: abort(); default: // Personality routine returned an unknown result code. _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", personalityResult); return _URC_FATAL_PHASE2_ERROR; } } frame_count++; } // Clean up phase did not resume at the frame that the search phase // said it would... return _URC_FATAL_PHASE2_ERROR; } /// Called by __cxa_throw. Only returns if there is a fatal error. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", static_cast(exception_object)); unw_context_t uc; unw_cursor_t cursor; unw_getcontext(&uc); // This field for is for compatibility with GCC to say this isn't a forced // unwind. EHABI #7.2 exception_object->unwinder_cache.reserved1 = 0; // phase 1: the search phase _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); if (phase1 != _URC_NO_REASON) return phase1; // phase 2: the clean up phase return unwind_phase2(&uc, &cursor, exception_object, false); } _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { // This is to be called when exception handling completes to give us a chance // to perform any housekeeping. EHABI #7.2. But we have nothing to do here. (void)exception_object; } /// When _Unwind_RaiseException() is in phase2, it hands control /// to the personality function at each frame. The personality /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler /// geneated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) /// is implemented by having the code call __cxa_rethrow() which /// in turn calls _Unwind_Resume_or_Rethrow(). _LIBUNWIND_EXPORT void _Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", static_cast(exception_object)); unw_context_t uc; unw_cursor_t cursor; unw_getcontext(&uc); // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, // which is in the same position as private_1 below. // TODO(ajwong): Who wronte the above? Why is it true? unwind_phase2(&uc, &cursor, exception_object, true); // Clients assume _Unwind_Resume() does not return, so all we can do is abort. _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); } /// Called by personality handler during phase 2 to get LSDA for current frame. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_proc_info_t frameInfo; uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.lsda; _LIBUNWIND_TRACE_API( - "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx\n", + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx", static_cast(context), (long long)result); return result; } static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, void* valuep) { uint64_t value = 0; switch (representation) { case _UVRSD_UINT32: case _UVRSD_FLOAT: memcpy(&value, valuep, sizeof(uint32_t)); break; case _UVRSD_VFPX: case _UVRSD_UINT64: case _UVRSD_DOUBLE: memcpy(&value, valuep, sizeof(uint64_t)); break; } return value; } _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " - "rep=%d, value=0x%llX)\n", + "rep=%d, value=0x%llX)", static_cast(context), regclass, regno, representation, ValueAsBitPattern(representation, valuep)); unw_cursor_t *cursor = (unw_cursor_t *)context; switch (regclass) { case _UVRSC_CORE: if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), *(unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_WMMXC: if (representation != _UVRSD_UINT32 || regno > 3) return _UVRSR_FAILED; return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), *(unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) return _UVRSR_FAILED; if (representation == _UVRSD_VFPX) { // Can only touch d0-15 with FSTMFDX. if (regno > 15) return _UVRSR_FAILED; unw_save_vfp_as_X(cursor); } else { if (regno > 31) return _UVRSR_FAILED; } return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), *(unw_fpreg_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_WMMXD: if (representation != _UVRSD_DOUBLE || regno > 31) return _UVRSR_FAILED; return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), *(unw_fpreg_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; } _LIBUNWIND_ABORT("unsupported register class"); } static _Unwind_VRS_Result _Unwind_VRS_Get_Internal(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep) { unw_cursor_t *cursor = (unw_cursor_t *)context; switch (regclass) { case _UVRSC_CORE: if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), (unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_WMMXC: if (representation != _UVRSD_UINT32 || regno > 3) return _UVRSR_FAILED; return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno), (unw_word_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) return _UVRSR_FAILED; if (representation == _UVRSD_VFPX) { // Can only touch d0-15 with FSTMFDX. if (regno > 15) return _UVRSR_FAILED; unw_save_vfp_as_X(cursor); } else { if (regno > 31) return _UVRSR_FAILED; } return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno), (unw_fpreg_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_WMMXD: if (representation != _UVRSD_DOUBLE || regno > 31) return _UVRSR_FAILED; return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno), (unw_fpreg_t *)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; } _LIBUNWIND_ABORT("unsupported register class"); } _Unwind_VRS_Result _Unwind_VRS_Get( _Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep) { _Unwind_VRS_Result result = _Unwind_VRS_Get_Internal(context, regclass, regno, representation, valuep); _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, " - "rep=%d, value=0x%llX, result = %d)\n", + "rep=%d, value=0x%llX, result = %d)", static_cast(context), regclass, regno, representation, ValueAsBitPattern(representation, valuep), result); return result; } _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t discriminator, _Unwind_VRS_DataRepresentation representation) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, " - "discriminator=%d, representation=%d)\n", + "discriminator=%d, representation=%d)", static_cast(context), regclass, discriminator, representation); switch (regclass) { case _UVRSC_CORE: case _UVRSC_WMMXC: { if (representation != _UVRSD_UINT32) return _UVRSR_FAILED; // When popping SP from the stack, we don't want to override it from the // computed new stack location. See EHABI #7.5.4 table 3. bool poppedSP = false; uint32_t* sp; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; } for (uint32_t i = 0; i < 16; ++i) { if (!(discriminator & static_cast(1 << i))) continue; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) poppedSP = true; if (_Unwind_VRS_Set(context, regclass, i, _UVRSD_UINT32, &value) != _UVRSR_OK) { return _UVRSR_FAILED; } } if (!poppedSP) { return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } return _UVRSR_OK; } case _UVRSC_VFP: case _UVRSC_WMMXD: { if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE) return _UVRSR_FAILED; uint32_t first = discriminator >> 16; uint32_t count = discriminator & 0xffff; uint32_t end = first+count; uint32_t* sp; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; } // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard // format 1", which is equivalent to FSTMD + a padding word. for (uint32_t i = first; i < end; ++i) { // SP is only 32-bit aligned so don't copy 64-bit at a time. uint64_t value = *sp++; value |= ((uint64_t)(*sp++)) << 32; if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != _UVRSR_OK) return _UVRSR_FAILED; } if (representation == _UVRSD_VFPX) ++sp; return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } } _LIBUNWIND_ABORT("unsupported register class"); } /// Called by personality handler during phase 2 to find the start of the /// function. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_proc_info_t frameInfo; uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX\n", + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX", static_cast(context), (long long)result); return result; } /// Called by personality handler during phase 2 if a foreign exception // is caught. _LIBUNWIND_EXPORT void _Unwind_DeleteException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", static_cast(exception_object)); if (exception_object->exception_cleanup != NULL) (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); } extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *exception_object, struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; if (unw_step(cursor) != UNW_STEP_SUCCESS) return _URC_FAILURE; return _URC_OK; } #endif // _LIBUNWIND_ARM_EHABI Index: stable/11/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/Unwind-sjlj.c (revision 312447) @@ -1,468 +1,468 @@ //===--------------------------- Unwind-sjlj.c ----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Implements setjump-longjump based C++ exceptions // //===----------------------------------------------------------------------===// #include #include #include #include #include "config.h" #include "unwind_ext.h" // // 32-bit iOS uses setjump/longjump based C++ exceptions. // Other architectures use "zero cost" exceptions. // // With SJLJ based exceptions, any function that has a catch clause or needs to // do any clean up when an exception propagates through it, needs to call // _Unwind_SjLj_Register() at the start of the function and // _Unwind_SjLj_Unregister() at the end. The register function is called with // the address of a block of memory in the function's stack frame. The runtime // keeps a linked list (stack) of these blocks - one per thread. The calling // function also sets the personality and lsda fields of the block. // #if _LIBUNWIND_BUILD_SJLJ_APIS struct _Unwind_FunctionContext { // next function in stack of handlers struct _Unwind_FunctionContext *prev; // set by calling function before registering to be the landing pad uintptr_t resumeLocation; // set by personality handler to be parameters passed to landing pad function uintptr_t resumeParameters[4]; // set by calling function before registering __personality_routine personality; // arm offset=24 uintptr_t lsda; // arm offset=28 // variable length array, contains registers to restore // 0 = r7, 1 = pc, 2 = sp void *jbuf[]; }; /// Called at start of each function that catches exceptions _LIBUNWIND_EXPORT void _Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) { fc->prev = __Unwind_SjLj_GetTopOfFunctionStack(); __Unwind_SjLj_SetTopOfFunctionStack(fc); } /// Called at end of each function that catches exceptions _LIBUNWIND_EXPORT void _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) { __Unwind_SjLj_SetTopOfFunctionStack(fc->prev); } static _Unwind_Reason_Code unwind_phase1(struct _Unwind_Exception *exception_object) { _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p\n", c); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c); // walk each frame looking for a place to stop for (bool handlerNotFound = true; handlerNotFound; c = c->prev) { // check for no more frames if (c == NULL) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached " - "bottom => _URC_END_OF_STACK\n", + "bottom => _URC_END_OF_STACK", exception_object); return _URC_END_OF_STACK; } - _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p\n", c); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c); // if there is a personality routine, ask it if it will want to stop at this // frame if (c->personality != NULL) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling " - "personality function %p\n", + "personality function %p", exception_object, c->personality); _Unwind_Reason_Code personalityResult = (*c->personality)( 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, (struct _Unwind_Context *)c); switch (personalityResult) { case _URC_HANDLER_FOUND: // found a catch clause or locals that need destructing in this frame // stop search and remember function context handlerNotFound = false; exception_object->private_2 = (uintptr_t) c; _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_HANDLER_FOUND\n", exception_object); + "_URC_HANDLER_FOUND", exception_object); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " - "_URC_CONTINUE_UNWIND\n", exception_object); + "_URC_CONTINUE_UNWIND", exception_object); // continue unwinding break; default: // something went wrong _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", exception_object); return _URC_FATAL_PHASE1_ERROR; } } } return _URC_NO_REASON; } static _Unwind_Reason_Code unwind_phase2(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object); // walk each frame until we reach where search phase said to stop _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); while (true) { - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p\n", + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p", exception_object, c); // check for no more frames if (c == NULL) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", + "bottom => _URC_END_OF_STACK", exception_object); return _URC_END_OF_STACK; } // if there is a personality routine, tell it we are unwinding if (c->personality != NULL) { _Unwind_Action action = _UA_CLEANUP_PHASE; if ((uintptr_t) c == exception_object->private_2) action = (_Unwind_Action)( _UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); // tell personality this was the frame it marked // in phase 1 _Unwind_Reason_Code personalityResult = (*c->personality)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)c); switch (personalityResult) { case _URC_CONTINUE_UNWIND: // continue unwinding _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", exception_object); if ((uintptr_t) c == exception_object->private_2) { // phase 1 said we would stop at this frame, but we did not... _LIBUNWIND_ABORT("during phase1 personality function said it would " "stop here, but now if phase2 it did not stop here"); } break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): " "_URC_INSTALL_CONTEXT, will resume at " - "landing pad %p\n", + "landing pad %p", exception_object, c->jbuf[1]); // personality routine says to transfer control to landing pad // we may get control back if landing pad calls _Unwind_Resume() __Unwind_SjLj_SetTopOfFunctionStack(c); __builtin_longjmp(c->jbuf, 1); // unw_resume() only returns if there was an error return _URC_FATAL_PHASE2_ERROR; default: // something went wrong _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", personalityResult); return _URC_FATAL_PHASE2_ERROR; } } c = c->prev; } // clean up phase did not resume at the frame that the search phase said it // would return _URC_FATAL_PHASE2_ERROR; } static _Unwind_Reason_Code unwind_phase2_forced(struct _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, void *stop_parameter) { // walk each frame until we reach where search phase said to stop _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); while (true) { // get next frame (skip over first which is _Unwind_RaiseException) if (c == NULL) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", + "bottom => _URC_END_OF_STACK", exception_object); return _URC_END_OF_STACK; } // call stop function at each frame _Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); _Unwind_Reason_Code stopResult = (*stop)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)c, stop_parameter); _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "stop function returned %d\n", + "stop function returned %d", exception_object, stopResult); if (stopResult != _URC_NO_REASON) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "stopped by stop function\n", + "stopped by stop function", exception_object); return _URC_FATAL_PHASE2_ERROR; } // if there is a personality routine, tell it we are unwinding if (c->personality != NULL) { __personality_routine p = (__personality_routine) c->personality; _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "calling personality function %p\n", + "calling personality function %p", exception_object, p); _Unwind_Reason_Code personalityResult = (*p)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)c); switch (personalityResult) { case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_CONTINUE_UNWIND\n", + "personality returned _URC_CONTINUE_UNWIND", exception_object); // destructors called, continue unwinding break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " - "personality returned _URC_INSTALL_CONTEXT\n", + "personality returned _URC_INSTALL_CONTEXT", exception_object); // we may get control back if landing pad calls _Unwind_Resume() __Unwind_SjLj_SetTopOfFunctionStack(c); __builtin_longjmp(c->jbuf, 1); break; default: // something went wrong _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " "personality returned %d, " - "_URC_FATAL_PHASE2_ERROR\n", + "_URC_FATAL_PHASE2_ERROR", exception_object, personalityResult); return _URC_FATAL_PHASE2_ERROR; } } c = c->prev; } // call stop function one last time and tell it we've reached the end of the // stack _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK\n", + "function with _UA_END_OF_STACK", exception_object); _Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); (*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context *)c, stop_parameter); // clean up phase did not resume at the frame that the search phase said it // would return _URC_FATAL_PHASE2_ERROR; } /// Called by __cxa_throw. Only returns if there is a fatal error _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object); + _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object); // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right // thing exception_object->private_1 = 0; exception_object->private_2 = 0; // phase 1: the search phase _Unwind_Reason_Code phase1 = unwind_phase1(exception_object); if (phase1 != _URC_NO_REASON) return phase1; // phase 2: the clean up phase return unwind_phase2(exception_object); } /// When _Unwind_RaiseException() is in phase2, it hands control /// to the personality function at each frame. The personality /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler /// geneated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Re-throwing an exception is implemented by having the code call /// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() _LIBUNWIND_EXPORT void _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object); + _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object); if (exception_object->private_1 != 0) unwind_phase2_forced(exception_object, (_Unwind_Stop_Fn) exception_object->private_1, (void *)exception_object->private_2); else unwind_phase2(exception_object); // clients assume _Unwind_Resume() does not return, so all we can do is abort. _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return"); } /// Called by __cxa_rethrow(). _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), " - "private_1=%ld\n", + "private_1=%ld", exception_object, exception_object->private_1); // If this is non-forced and a stopping place was found, then this is a // re-throw. // Call _Unwind_RaiseException() as if this was a new exception. if (exception_object->private_1 == 0) { return _Unwind_SjLj_RaiseException(exception_object); // should return if there is no catch clause, so that __cxa_rethrow can call // std::terminate() } // Call through to _Unwind_Resume() which distiguishes between forced and // regular exceptions. _Unwind_SjLj_Resume(exception_object); _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " "_Unwind_SjLj_Resume() which unexpectedly returned"); } /// Called by personality handler during phase 2 to get LSDA for current frame. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " - "=> 0x%0lX\n", context, ufc->lsda); + "=> 0x%0lX", context, ufc->lsda); return ufc->lsda; } /// Called by personality handler during phase 2 to get register values. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { - _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)\n", + _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", context, index); _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; return ufc->resumeParameters[index]; } /// Called by personality handler during phase 2 to alter register values. _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n" + _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)" , context, index, new_value); _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; ufc->resumeParameters[index] = new_value; } /// Called by personality handler during phase 2 to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context, + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context, ufc->resumeLocation + 1); return ufc->resumeLocation + 1; } /// Called by personality handler during phase 2 to get instruction pointer. /// ipBefore is a boolean that says if IP is already adjusted to be the call /// site address. Normally IP is the return address. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *ipBefore) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; *ipBefore = 0; - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n", + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX", context, ipBefore, ufc->resumeLocation + 1); return ufc->resumeLocation + 1; } /// Called by personality handler during phase 2 to alter instruction pointer. _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) { - _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n", + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)", context, new_value); _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; ufc->resumeLocation = new_value - 1; } /// Called by personality handler during phase 2 to find the start of the /// function. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { // Not supported or needed for sjlj based unwinding (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context); return 0; } /// Called by personality handler during phase 2 if a foreign exception /// is caught. _LIBUNWIND_EXPORT void _Unwind_DeleteException(struct _Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", exception_object); if (exception_object->exception_cleanup != NULL) (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); } /// Called by personality handler during phase 2 to get base address for data /// relative encodings. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) { // Not supported or needed for sjlj based unwinding (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context); _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); } /// Called by personality handler during phase 2 to get base address for text /// relative encodings. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { // Not supported or needed for sjlj based unwinding (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context); _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); } /// Called by personality handler to get "Call Frame Area" for current frame. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { - _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)\n", context); + _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context); if (context != NULL) { _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; // Setjmp/longjmp based exceptions don't have a true CFA. // Instead, the SP in the jmpbuf is the closest approximation. return (uintptr_t) ufc->jbuf[2]; } return 0; } #endif // _LIBUNWIND_BUILD_SJLJ_APIS Index: stable/11/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp (revision 312447) @@ -1,1372 +1,1372 @@ //===------------------------- UnwindCursor.hpp ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // -// C++ interface to lower levels of libuwind +// C++ interface to lower levels of libunwind //===----------------------------------------------------------------------===// #ifndef __UNWINDCURSOR_HPP__ #define __UNWINDCURSOR_HPP__ #include #include #include #include #include #include #ifdef __APPLE__ #include #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 "Unwind-EHABI.h" namespace libunwind { #if _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 pthread_rwlock_t _lock; #ifdef __APPLE__ static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); static bool _registeredForDyldUnloads; #endif // Can't use std::vector<> here because this code is below libc++. static entry *_buffer; static entry *_bufferUsed; static entry *_bufferEnd; 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 pthread_rwlock_t DwarfFDECache::_lock = PTHREAD_RWLOCK_INITIALIZER; #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_NON_ZERO(::pthread_rwlock_rdlock(&_lock)); 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_NON_ZERO(::pthread_rwlock_unlock(&_lock)); 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_NON_ZERO(::pthread_rwlock_wrlock(&_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_NON_ZERO(::pthread_rwlock_unlock(&_lock)); #endif } template void DwarfFDECache::removeAllIn(pint_t mh) { _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_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_NON_ZERO(::pthread_rwlock_unlock(&_lock)); } #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_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); for (entry *p = _buffer; p < _bufferUsed; ++p) { (*func)(p->ip_start, p->ip_end, p->fde, p->mh); } _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); } #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) #if _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 // _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 }; /// 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 private: #if _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 _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); } #endif #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND bool getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s); int stepWithCompactEncoding() { #if _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_AARCH64) int stepWithCompactEncoding(Registers_arm64 &) { return CompactUnwinder_arm64::stepWithCompactEncoding( _info.format, _info.start_ip, _addressSpace, _registers); } #endif bool compactSaysUseDwarf(uint32_t *offset=NULL) const { R dummy; return compactSaysUseDwarf(dummy, offset); } #if defined(_LIBUNWIND_TARGET_X86_64) bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { if (offset) *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_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 #endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND #if _LIBUNWIND_SUPPORT_DWARF_UNWIND compact_unwind_encoding_t dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); } #if defined(_LIBUNWIND_TARGET_X86_64) compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { return UNWIND_X86_64_MODE_DWARF; } #endif #if defined(_LIBUNWIND_TARGET_I386) compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { return UNWIND_X86_MODE_DWARF; } #endif #if defined(_LIBUNWIND_TARGET_PPC) compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { return 0; } #endif #if defined(_LIBUNWIND_TARGET_AARCH64) compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { return UNWIND_ARM64_MODE_DWARF; } #endif #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 #endif // _LIBUNWIND_SUPPORT_DWARF_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; } #if _LIBUNWIND_ARM_EHABI struct EHABIIndexEntry { uint32_t functionOffset; uint32_t data; }; template struct EHABISectionIterator { typedef EHABISectionIterator _Self; typedef std::random_access_iterator_tag iterator_category; typedef typename A::pint_t value_type; typedef typename A::pint_t* pointer; typedef typename A::pint_t& reference; 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); } 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; }; template bool UnwindCursor::getInfoFromEHABISection( pint_t pc, const UnwindInfoSections §s) { EHABISectionIterator begin = EHABISectionIterator::begin(_addressSpace, sects); EHABISectionIterator end = EHABISectionIterator::end(_addressSpace, sects); EHABISectionIterator itNextPC = std::upper_bound(begin, end, pc); if (itNextPC == begin || itNextPC == end) return false; EHABISectionIterator itThisPC = itNextPC - 1; pint_t thisPC = itThisPC.functionAddress(); pint_t nextPC = 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 _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 _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, &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 _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\n", (uint64_t)pc); + //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); return false; } #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND #if _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\n", + "level compressed unwind table. funcStart=0x%llX", (uint64_t) pc, (uint64_t) funcStart); return false; } if (pc > funcEnd) { _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " - "level compressed unwind table. funcEnd=0x%llX\n", + "level compressed unwind table. funcEnd=0x%llX", (uint64_t) pc, (uint64_t) funcEnd); return false; } 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\n", + "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\n", + "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 entires\n", + "but personality table has only %d entires", 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 // _LIBUNWIND_SUPPORT_COMPACT_UNWIND template void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { pint_t pc = (pint_t)this->getReg(UNW_REG_IP); #if _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 _LIBUNWIND_SUPPORT_COMPACT_UNWIND // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { if (this->getInfoFromCompactEncodingSection(pc, sects)) { #if _LIBUNWIND_SUPPORT_DWARF_UNWIND // 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 // _LIBUNWIND_SUPPORT_COMPACT_UNWIND #if _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 _LIBUNWIND_ARM_EHABI // If there is ARM EHABI unwind info, look there next. if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) return; #endif } #if _LIBUNWIND_SUPPORT_DWARF_UNWIND // 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, &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, &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 _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 _LIBUNWIND_SUPPORT_COMPACT_UNWIND result = this->stepWithCompactEncoding(); #elif _LIBUNWIND_SUPPORT_DWARF_UNWIND result = this->stepWithDwarfFDE(); #elif _LIBUNWIND_ARM_EHABI result = this->stepWithEHABI(); #else #error Need _LIBUNWIND_SUPPORT_COMPACT_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; if (_info.gp) setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp); } return result; } template void UnwindCursor::getInfo(unw_proc_info_t *info) { *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: stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c (revision 312447) @@ -1,316 +1,316 @@ //===--------------------- UnwindLevel1-gcc-ext.c -------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Implements gcc extensions to the C++ ABI Exception Handling Level 1. // //===----------------------------------------------------------------------===// #include #include #include #include #include #include #include "config.h" #include "libunwind_ext.h" #include "libunwind.h" #include "Unwind-EHABI.h" #include "unwind.h" #if _LIBUNWIND_BUILD_ZERO_COST_APIS /// Called by __cxa_rethrow(). _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { #if _LIBUNWIND_ARM_EHABI - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", (void *)exception_object, (long)exception_object->unwinder_cache.reserved1); #else - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", + _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", (void *)exception_object, (long)exception_object->private_1); #endif #if _LIBUNWIND_ARM_EHABI // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, // which is in the same position as private_1 below. return _Unwind_RaiseException(exception_object); #else // If this is non-forced and a stopping place was found, then this is a // re-throw. // Call _Unwind_RaiseException() as if this was a new exception if (exception_object->private_1 == 0) { return _Unwind_RaiseException(exception_object); // Will return if there is no catch clause, so that __cxa_rethrow can call // std::terminate(). } // Call through to _Unwind_Resume() which distiguishes between forced and // regular exceptions. _Unwind_Resume(exception_object); _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" " which unexpectedly returned"); #endif } /// Called by personality handler during phase 2 to get base address for data /// relative encodings. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) { (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)\n", (void *)context); + _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context); _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); } /// Called by personality handler during phase 2 to get base address for text /// relative encodings. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { (void)context; - _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", (void *)context); + _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context); _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); } /// Scans unwind information to find the function that contains the /// specified code address "pc". _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { - _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc); + _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); // This is slow, but works. // We create an unwind cursor then alter the IP to be pc unw_cursor_t cursor; unw_context_t uc; unw_proc_info_t info; unw_getcontext(&uc); unw_init_local(&cursor, &uc); unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc); if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS) return (void *)(long) info.start_ip; else return NULL; } /// Walk every frame and call trace function at each one. If trace function /// returns anything other than _URC_NO_REASON, then walk is terminated. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { unw_cursor_t cursor; unw_context_t uc; unw_getcontext(&uc); unw_init_local(&cursor, &uc); - _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)", (void *)(uintptr_t)callback); #if _LIBUNWIND_ARM_EHABI // Create a mock exception object for force unwinding. _Unwind_Exception ex; memset(&ex, '\0', sizeof(ex)); ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 #endif // walk each frame while (true) { _Unwind_Reason_Code result; #if !_LIBUNWIND_ARM_EHABI - // ask libuwind to get next frame (skip over first frame which is + // ask libunwind to get next frame (skip over first frame which is // _Unwind_Backtrace()) if (unw_step(&cursor) <= 0) { _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached " - "bottom of stack, returning %d\n", + "bottom of stack, returning %d", _URC_END_OF_STACK); return _URC_END_OF_STACK; } #else // Get the information for this frame. unw_proc_info_t frameInfo; if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) { return _URC_END_OF_STACK; } // Update the pr_cache in the mock exception object. const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info; ex.pr_cache.fnstart = frameInfo.start_ip; ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo; ex.pr_cache.additional= frameInfo.flags; struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; // Get and call the personality function to unwind the frame. __personality_routine handler = (__personality_routine) frameInfo.handler; if (handler == NULL) { return _URC_END_OF_STACK; } if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) != _URC_CONTINUE_UNWIND) { return _URC_END_OF_STACK; } #endif // _LIBUNWIND_ARM_EHABI // debugging if (_LIBUNWIND_TRACING_UNWINDING) { char functionName[512]; unw_proc_info_t frame; unw_word_t offset; unw_get_proc_name(&cursor, functionName, 512, &offset); unw_get_proc_info(&cursor, &frame); _LIBUNWIND_TRACE_UNWINDING( - " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n", + " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p", (long long)frame.start_ip, functionName, (long long)frame.lsda, (void *)&cursor); } // call trace function with this frame result = (*callback)((struct _Unwind_Context *)(&cursor), ref); if (result != _URC_NO_REASON) { _LIBUNWIND_TRACE_UNWINDING( - " _backtrace: ended because callback returned %d\n", result); + " _backtrace: ended because callback returned %d", result); return result; } } } /// Find dwarf unwind info for an address 'pc' in some function. _LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *bases) { // This is slow, but works. // We create an unwind cursor then alter the IP to be pc unw_cursor_t cursor; unw_context_t uc; unw_proc_info_t info; unw_getcontext(&uc); unw_init_local(&cursor, &uc); unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long) pc); unw_get_proc_info(&cursor, &info); bases->tbase = (uintptr_t)info.extra; bases->dbase = 0; // dbase not used on Mac OS X bases->func = (uintptr_t)info.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p\n", pc, + _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc, (void *)(long) info.unwind_info); return (void *)(long) info.unwind_info; } /// Returns the CFA (call frame area, or stack pointer at start of function) /// for the current context. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, UNW_REG_SP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64 "\n", + _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIx64, (void *)context, (uint64_t)result); return (uintptr_t)result; } /// Called by personality handler during phase 2 to get instruction pointer. /// ipBefore is a boolean that says if IP is already adjusted to be the call /// site address. Normally IP is the return address. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *ipBefore) { - _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)\n", (void *)context); + _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context); *ipBefore = 0; return _Unwind_GetIP(context); } #if _LIBUNWIND_SUPPORT_DWARF_UNWIND /// Called by programs with dynamic code generators that want /// to register a dynamically generated FDE. /// This function has existed on Mac OS X since 10.4, but /// was broken until 10.6. _LIBUNWIND_EXPORT void __register_frame(const void *fde) { - _LIBUNWIND_TRACE_API("__register_frame(%p)\n", fde); + _LIBUNWIND_TRACE_API("__register_frame(%p)", fde); _unw_add_dynamic_fde((unw_word_t)(uintptr_t) fde); } /// Called by programs with dynamic code generators that want /// to unregister a dynamically generated FDE. /// This function has existed on Mac OS X since 10.4, but /// was broken until 10.6. _LIBUNWIND_EXPORT void __deregister_frame(const void *fde) { - _LIBUNWIND_TRACE_API("__deregister_frame(%p)\n", fde); + _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde); _unw_remove_dynamic_fde((unw_word_t)(uintptr_t) fde); } // The following register/deregister functions are gcc extensions. // They have existed on Mac OS X, but have never worked because Mac OS X // before 10.6 used keymgr to track known FDEs, but these functions // never got updated to use keymgr. // For now, we implement these as do-nothing functions to keep any existing // applications working. We also add the not in 10.6 symbol so that nwe // application won't be able to use them. #if _LIBUNWIND_SUPPORT_FRAME_APIS _LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob, void *tb, void *db) { (void)fde; (void)ob; (void)tb; (void)db; - _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)\n", + _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)", fde, ob, tb, db); // do nothing, this function never worked in Mac OS X } _LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) { (void)fde; (void)ob; - _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)\n", fde, ob); + _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob); // do nothing, this function never worked in Mac OS X } _LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde, void *ob, void *tb, void *db) { (void)fde; (void)ob; (void)tb; (void)db; _LIBUNWIND_TRACE_API("__register_frame_info_table_bases" - "(%p,%p, %p, %p)\n", fde, ob, tb, db); + "(%p,%p, %p, %p)", fde, ob, tb, db); // do nothing, this function never worked in Mac OS X } _LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) { (void)fde; (void)ob; - _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)\n", fde, ob); + _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob); // do nothing, this function never worked in Mac OS X } _LIBUNWIND_EXPORT void __register_frame_table(const void *fde) { (void)fde; - _LIBUNWIND_TRACE_API("__register_frame_table(%p)\n", fde); + _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde); // do nothing, this function never worked in Mac OS X } _LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) { (void)fde; - _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)\n", fde); + _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde); // do nothing, this function never worked in Mac OS X return NULL; } _LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) { (void)fde; - _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)\n", fde); + _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde); // do nothing, this function never worked in Mac OS X return NULL; } #endif // _LIBUNWIND_SUPPORT_FRAME_APIS #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND #endif // _LIBUNWIND_BUILD_ZERO_COST_APIS Index: stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1.c =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1.c (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/UnwindLevel1.c (revision 312447) @@ -1,506 +1,506 @@ //===------------------------- UnwindLevel1.c -----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Implements C++ ABI Exception Handling Level 1 as documented at: // http://mentorembedded.github.io/cxx-abi/abi-eh.html // using libunwind // //===----------------------------------------------------------------------===// // ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are // defining inline functions to delegate the function calls to // _Unwind_VRS_{Get,Set}(). However, some applications might declare the // function protetype directly (instead of including ), thus we need // to export these functions from libunwind.so as well. #define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1 #include #include #include #include #include #include #include "libunwind.h" #include "unwind.h" #include "config.h" #if !_LIBUNWIND_ARM_EHABI static _Unwind_Reason_Code unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { unw_init_local(cursor, uc); // Walk each frame looking for a place to stop. bool handlerNotFound = true; while (handlerNotFound) { - // Ask libuwind to get next frame (skip over first which is + // Ask libunwind to get next frame (skip over first which is // _Unwind_RaiseException). int stepResult = unw_step(cursor); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", + "bottom => _URC_END_OF_STACK", (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", + "_URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } // See if frame has code to run (has personality routine). unw_proc_info_t frameInfo; unw_word_t sp; if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", + "failed => _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; const char *functionName = functionBuf; unw_word_t offset; if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; unw_word_t pc; unw_get_reg(cursor, UNW_REG_IP, &pc); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64 - ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", + ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "", (void *)exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } // If there is a personality routine, ask it if it will want to stop at // this frame. if (frameInfo.handler != 0) { __personality_routine p = (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): calling personality function %p\n", + "unwind_phase1(ex_ojb=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor)); switch (personalityResult) { case _URC_HANDLER_FOUND: // found a catch clause or locals that need destructing in this frame // stop search and remember stack pointer at the frame handlerNotFound = false; unw_get_reg(cursor, UNW_REG_SP, &sp); exception_object->private_2 = (uintptr_t)sp; _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n", + "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", (void *)exception_object); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", + "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", (void *)exception_object); // continue unwinding break; default: // something went wrong _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", + "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } } } return _URC_NO_REASON; } static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { unw_init_local(cursor, uc); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", (void *)exception_object); // Walk each frame until we reach where search phase said to stop. while (true) { - // Ask libuwind to get next frame (skip over first which is + // Ask libunwind to get next frame (skip over first which is // _Unwind_RaiseException). int stepResult = unw_step(cursor); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " - "bottom => _URC_END_OF_STACK\n", + "bottom => _URC_END_OF_STACK", (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " - "_URC_FATAL_PHASE1_ERROR\n", + "_URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // Get info about this frame. unw_word_t sp; unw_proc_info_t frameInfo; unw_get_reg(cursor, UNW_REG_SP, &sp); if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " - "failed => _URC_FATAL_PHASE1_ERROR\n", + "failed => _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; const char *functionName = functionBuf; unw_word_t offset; if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64 ", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64 - ", personality=0x%" PRIx64 "\n", + ", personality=0x%" PRIx64, (void *)exception_object, frameInfo.start_ip, functionName, sp, frameInfo.lsda, frameInfo.handler); } // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { __personality_routine p = (__personality_routine)(long)(frameInfo.handler); _Unwind_Action action = _UA_CLEANUP_PHASE; if (sp == exception_object->private_2) { // Tell personality this was the frame it marked in phase 1. action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); } _Unwind_Reason_Code personalityResult = (*p)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor)); switch (personalityResult) { case _URC_CONTINUE_UNWIND: // Continue unwinding _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", + "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", (void *)exception_object); if (sp == exception_object->private_2) { // Phase 1 said we would stop at this frame, but we did not... _LIBUNWIND_ABORT("during phase1 personality function said it would " "stop here, but now in phase2 it did not stop here"); } break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", + "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", (void *)exception_object); // Personality routine says to transfer control to landing pad. // We may get control back if landing pad calls _Unwind_Resume(). if (_LIBUNWIND_TRACING_UNWINDING) { unw_word_t pc; unw_get_reg(cursor, UNW_REG_IP, &pc); unw_get_reg(cursor, UNW_REG_SP, &sp); _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " "user code with ip=0x%" PRIx64 - ", sp=0x%" PRIx64 "\n", + ", sp=0x%" PRIx64, (void *)exception_object, pc, sp); } unw_resume(cursor); // unw_resume() only returns if there was an error. return _URC_FATAL_PHASE2_ERROR; default: // Personality routine returned an unknown result code. _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", personalityResult); return _URC_FATAL_PHASE2_ERROR; } } } // Clean up phase did not resume at the frame that the search phase // said it would... return _URC_FATAL_PHASE2_ERROR; } static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, void *stop_parameter) { unw_init_local(cursor, uc); // Walk each frame until we reach where search phase said to stop while (unw_step(cursor) > 0) { // Update info about this frame. unw_proc_info_t frameInfo; if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " - "failed => _URC_END_OF_STACK\n", + "failed => _URC_END_OF_STACK", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; const char *functionName = functionBuf; unw_word_t offset; if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING( "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64 - ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n", + ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } // Call stop function at each frame. _Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); _Unwind_Reason_Code stopResult = (*stop)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor), stop_parameter); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", + "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", (void *)exception_object, stopResult); if (stopResult != _URC_NO_REASON) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", + "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { __personality_routine p = (__personality_routine)(long)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", + "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor)); switch (personalityResult) { case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " "personality returned " - "_URC_CONTINUE_UNWIND\n", + "_URC_CONTINUE_UNWIND", (void *)exception_object); // Destructors called, continue unwinding break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " "personality returned " - "_URC_INSTALL_CONTEXT\n", + "_URC_INSTALL_CONTEXT", (void *)exception_object); // We may get control back if landing pad calls _Unwind_Resume(). unw_resume(cursor); break; default: // Personality routine returned an unknown result code. _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " "personality returned %d, " - "_URC_FATAL_PHASE2_ERROR\n", + "_URC_FATAL_PHASE2_ERROR", (void *)exception_object, personalityResult); return _URC_FATAL_PHASE2_ERROR; } } } // Call stop function one last time and tell it we've reached the end // of the stack. _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " - "function with _UA_END_OF_STACK\n", + "function with _UA_END_OF_STACK", (void *)exception_object); _Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); (*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor), stop_parameter); // Clean up phase did not resume at the frame that the search phase said it // would. return _URC_FATAL_PHASE2_ERROR; } /// Called by __cxa_throw. Only returns if there is a fatal error. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", (void *)exception_object); unw_context_t uc; unw_cursor_t cursor; unw_getcontext(&uc); // Mark that this is a non-forced unwind, so _Unwind_Resume() // can do the right thing. exception_object->private_1 = 0; exception_object->private_2 = 0; // phase 1: the search phase _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); if (phase1 != _URC_NO_REASON) return phase1; // phase 2: the clean up phase return unwind_phase2(&uc, &cursor, exception_object); } /// When _Unwind_RaiseException() is in phase2, it hands control /// to the personality function at each frame. The personality /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler /// geneated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) /// is implemented by having the code call __cxa_rethrow() which /// in turn calls _Unwind_Resume_or_Rethrow(). _LIBUNWIND_EXPORT void _Unwind_Resume(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object); + _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); unw_context_t uc; unw_cursor_t cursor; unw_getcontext(&uc); if (exception_object->private_1 != 0) unwind_phase2_forced(&uc, &cursor, exception_object, (_Unwind_Stop_Fn) exception_object->private_1, (void *)exception_object->private_2); else unwind_phase2(&uc, &cursor, exception_object); // Clients assume _Unwind_Resume() does not return, so all we can do is abort. _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); } /// Not used by C++. /// Unwinds stack, calling "stop" function at each frame. /// Could be used to implement longjmp(). _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, void *stop_parameter) { - _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", (void *)exception_object, (void *)(uintptr_t)stop); unw_context_t uc; unw_cursor_t cursor; unw_getcontext(&uc); // Mark that this is a forced unwind, so _Unwind_Resume() can do // the right thing. exception_object->private_1 = (uintptr_t) stop; exception_object->private_2 = (uintptr_t) stop_parameter; // do it return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter); } /// Called by personality handler during phase 2 to get LSDA for current frame. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_proc_info_t frameInfo; uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.lsda; _LIBUNWIND_TRACE_API( - "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR "\n", + "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, (void *)context, result); if (result != 0) { if (*((uint8_t *)result) != 0xFF) - _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n", + _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF", result); } return result; } /// Called by personality handler during phase 2 to find the start of the /// function. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_proc_info_t frameInfo; uintptr_t result = 0; if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) result = (uintptr_t)frameInfo.start_ip; - _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR "\n", + _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, (void *)context, result); return result; } /// Called by personality handler during phase 2 if a foreign exception // is caught. _LIBUNWIND_EXPORT void _Unwind_DeleteException(_Unwind_Exception *exception_object) { - _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", + _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", (void *)exception_object); if (exception_object->exception_cleanup != NULL) (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); } /// Called by personality handler during phase 2 to get register values. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, index, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", + _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64, (void *)context, index, (uint64_t)result); return (uintptr_t)result; } /// Called by personality handler during phase 2 to alter register values. _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, uintptr_t value) { _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIx64 - ")\n", + ")", (void *)context, index, (uint64_t)value); unw_cursor_t *cursor = (unw_cursor_t *)context; unw_set_reg(cursor, index, value); } /// Called by personality handler during phase 2 to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, UNW_REG_IP, &result); - _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64 "\n", + _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIx64, (void *)context, (uint64_t)result); return (uintptr_t)result; } /// Called by personality handler during phase 2 to alter instruction pointer, /// such as setting where the landing pad is, so _Unwind_Resume() will /// start executing in the landing pad. _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { - _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")\n", + _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIx64 ")", (void *)context, (uint64_t)value); unw_cursor_t *cursor = (unw_cursor_t *)context; unw_set_reg(cursor, UNW_REG_IP, value); } #endif // !_LIBUNWIND_ARM_EHABI Index: stable/11/contrib/llvm/projects/libunwind/src/config.h =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/config.h (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/config.h (revision 312447) @@ -1,144 +1,144 @@ //===----------------------------- config.h -------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // -// Defines macros used within libuwind project. +// Defines macros used within libunwind project. // //===----------------------------------------------------------------------===// #ifndef LIBUNWIND_CONFIG_H #define LIBUNWIND_CONFIG_H #include #include #include // Define static_assert() unless already defined by compiler. #ifndef __has_feature #define __has_feature(__x) 0 #endif #if !(__has_feature(cxx_static_assert)) && !defined(static_assert) #define static_assert(__b, __m) \ extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \ __attribute__( ( unused ) ); #endif // Platform specific configuration defines. #ifdef __APPLE__ #if defined(FOR_DYLD) #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 #else #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 #endif #else #if defined(__ARM_DWARF_EH__) || !defined(__arm__) #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 #else #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 #endif #endif // FIXME: these macros are not correct for COFF targets #define _LIBUNWIND_EXPORT __attribute__((visibility("default"))) #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden"))) #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) #define _LIBUNWIND_BUILD_SJLJ_APIS 1 #else #define _LIBUNWIND_BUILD_SJLJ_APIS 0 #endif #if defined(__i386__) || defined(__x86_64__) #define _LIBUNWIND_SUPPORT_FRAME_APIS 1 #else #define _LIBUNWIND_SUPPORT_FRAME_APIS 0 #endif #if defined(__i386__) || defined(__x86_64__) || \ (!defined(__APPLE__) && defined(__arm__)) || \ (defined(__arm64__) || defined(__aarch64__)) || \ (defined(__APPLE__) && defined(__mips__)) || \ defined(__riscv__) #define _LIBUNWIND_BUILD_ZERO_COST_APIS 1 #else #define _LIBUNWIND_BUILD_ZERO_COST_APIS 0 #endif #define _LIBUNWIND_ABORT(msg) \ do { \ fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \ __LINE__, msg); \ fflush(stderr); \ abort(); \ } while (0) -#define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__) +#define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__) // Macros that define away in non-Debug builds #ifdef NDEBUG #define _LIBUNWIND_DEBUG_LOG(msg, ...) #define _LIBUNWIND_TRACE_API(msg, ...) #define _LIBUNWIND_TRACING_UNWINDING 0 #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) #define _LIBUNWIND_LOG_NON_ZERO(x) x #else #ifdef __cplusplus extern "C" { #endif extern bool logAPIs(); extern bool logUnwinding(); #ifdef __cplusplus } #endif #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__) #define _LIBUNWIND_LOG_NON_ZERO(x) \ do { \ int _err = x; \ if ( _err != 0 ) \ _LIBUNWIND_LOG("" #x "=%d in %s", _err, __FUNCTION__); \ } while (0) #define _LIBUNWIND_TRACE_API(msg, ...) \ do { \ if ( logAPIs() ) _LIBUNWIND_LOG(msg, __VA_ARGS__); \ } while(0) #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \ do { \ if ( logUnwinding() ) _LIBUNWIND_LOG(msg, __VA_ARGS__); \ } while(0) #define _LIBUNWIND_TRACING_UNWINDING logUnwinding() #endif #ifdef __cplusplus // Used to fit UnwindCursor and Registers_xxx types against unw_context_t / // unw_cursor_t sized memory blocks. #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # define COMP_OP == #else # define COMP_OP < #endif template struct check_fit { template struct blk_count { static const size_t count = (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t); }; static const bool does_fit = (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count); }; #undef COMP_OP #endif // __cplusplus #endif // LIBUNWIND_CONFIG_H Index: stable/11/contrib/llvm/projects/libunwind/src/libunwind.cpp =================================================================== --- stable/11/contrib/llvm/projects/libunwind/src/libunwind.cpp (revision 312446) +++ stable/11/contrib/llvm/projects/libunwind/src/libunwind.cpp (revision 312447) @@ -1,377 +1,377 @@ -//===--------------------------- libuwind.cpp -----------------------------===// +//===--------------------------- libunwind.cpp ----------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // // // Implements unw_* functions from // //===----------------------------------------------------------------------===// #include #ifndef NDEBUG #include // getenv #endif #include #include #include "libunwind_ext.h" #include "config.h" #include #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; /// record the registers and stack position of the caller extern int unw_getcontext(unw_context_t *); // note: unw_getcontext() implemented in assembly /// Create a cursor of a thread in this process given 'context' recorded by /// unw_getcontext(). _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, unw_context_t *context) { - _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)\n", + _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)", static_cast(cursor), static_cast(context)); #if defined(__i386__) # define REGISTER_KIND Registers_x86 #elif defined(__x86_64__) # define REGISTER_KIND Registers_x86_64 #elif defined(__ppc__) # define REGISTER_KIND Registers_ppc #elif defined(__aarch64__) # define REGISTER_KIND Registers_arm64 #elif _LIBUNWIND_ARM_EHABI # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k #elif defined(__riscv__) # define REGISTER_KIND Registers_riscv #elif defined(__mips__) # warning The MIPS architecture is not supported. #else # error Architecture not supported #endif // Use "placement new" to allocate UnwindCursor in the cursor buffer. new ((void *)cursor) UnwindCursor( context, LocalAddressSpace::sThisAddressSpace); #undef REGISTER_KIND AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->setInfoBasedOnIPRegister(); return UNW_ESUCCESS; } #ifdef UNW_REMOTE /// Create a cursor into a thread in another process. _LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor, unw_addr_space_t as, void *arg) { // special case: unw_init_remote(xx, unw_local_addr_space, xx) if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace) return unw_init_local(cursor, NULL); //FIXME // use "placement new" to allocate UnwindCursor in the cursor buffer switch (as->cpuType) { case CPU_TYPE_I386: new ((void *)cursor) UnwindCursor >, Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg); break; case CPU_TYPE_X86_64: new ((void *)cursor) UnwindCursor< OtherAddressSpace >, Registers_x86_64>( ((unw_addr_space_x86_64 *)as)->oas, arg); break; case CPU_TYPE_POWERPC: new ((void *)cursor) UnwindCursor >, Registers_ppc>( ((unw_addr_space_ppc *)as)->oas, arg); break; default: return UNW_EUNSPEC; } return UNW_ESUCCESS; } static bool is64bit(task_t task) { return false; // FIXME } /// Create an address_space object for use in examining another task. _LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) { #if __i386__ if (is64bit(task)) { unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task); as->taskPort = task; as->cpuType = CPU_TYPE_X86_64; //as->oas } else { unw_addr_space_i386 *as = new unw_addr_space_i386(task); as->taskPort = task; as->cpuType = CPU_TYPE_I386; //as->oas } #else // FIXME #endif } /// Delete an address_space object. _LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) { switch (asp->cpuType) { #if __i386__ || __x86_64__ case CPU_TYPE_I386: { unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp; delete as; } break; case CPU_TYPE_X86_64: { unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp; delete as; } break; #endif case CPU_TYPE_POWERPC: { unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp; delete as; } break; } } #endif // UNW_REMOTE /// Get value of specified register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t *value) { - _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)", static_cast(cursor), regNum, static_cast(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { *value = co->getReg(regNum); return UNW_ESUCCESS; } return UNW_EBADREG; } /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_word_t value) { - _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", + _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)", static_cast(cursor), regNum, (long long)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) co->setInfoBasedOnIPRegister(false); return UNW_ESUCCESS; } return UNW_EBADREG; } /// Get value of specified float register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t *value) { - _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)", static_cast(cursor), regNum, static_cast(value)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validFloatReg(regNum)) { *value = co->getFloatReg(regNum); return UNW_ESUCCESS; } return UNW_EBADREG; } /// Set value of specified float register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { #if _LIBUNWIND_ARM_EHABI - _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)\n", + _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)\n", + _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; } /// Move cursor to next frame. _LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_step(cursor=%p)\n", static_cast(cursor)); + _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->step(); } /// Get unwind info at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor, unw_proc_info_t *info) { - _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)\n", + _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)", static_cast(cursor), static_cast(info)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->getInfo(info); if (info->end_ip == 0) return UNW_ENOINFO; else return UNW_ESUCCESS; } /// Resume execution at cursor position (aka longjump). _LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)\n", static_cast(cursor)); + _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; co->jumpto(); return UNW_EUNSPEC; } /// Get name of function at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf, size_t bufLen, unw_word_t *offset) { - _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)\n", + _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)", static_cast(cursor), static_cast(buf), static_cast(bufLen)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->getFunctionName(buf, bufLen, offset)) return UNW_ESUCCESS; else return UNW_EUNSPEC; } /// Checks if a register is a floating-point register. _LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", + _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)", static_cast(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->validFloatReg(regNum); } /// Checks if a register is a floating-point register. _LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor, unw_regnum_t regNum) { - _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)\n", + _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)", static_cast(cursor), regNum); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->getRegisterName(regNum); } /// Checks if current frame is signal trampoline. _LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)\n", + _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->isSignalFrame(); } #ifdef __arm__ // Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD _LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) { - _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)\n", + _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)", static_cast(cursor)); AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; return co->saveVFPAsX(); } #endif #if _LIBUNWIND_SUPPORT_DWARF_UNWIND /// SPI: walks cached dwarf entries _LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", + _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)", reinterpret_cast(func)); DwarfFDECache::iterateCacheEntries(func); } /// 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 // _LIBUNWIND_SUPPORT_DWARF_UNWIND // 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; } #endif // NDEBUG Index: stable/11 =================================================================== --- stable/11 (revision 312446) +++ stable/11 (revision 312447) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r308006