Page MenuHomeFreeBSD

D5929.1790900286.diff
No OneTemporary

Size
582 KB
Referenced Files
None
Subscribers
None

D5929.1790900286.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: contrib/llvm/projects/libunwind/include/__libunwind_config.h
===================================================================
--- contrib/llvm/projects/libunwind/include/__libunwind_config.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//===------------------------- __libunwind_config.h -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ____LIBUNWIND_CONFIG_H__
-#define ____LIBUNWIND_CONFIG_H__
-
-#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
- !defined(__ARM_DWARF_EH__)
-#define _LIBUNWIND_ARM_EHABI 1
-#else
-#define _LIBUNWIND_ARM_EHABI 0
-#endif
-
-#endif // ____LIBUNWIND_CONFIG_H__
Index: contrib/llvm/projects/libunwind/include/libunwind.h
===================================================================
--- contrib/llvm/projects/libunwind/include/libunwind.h
+++ /dev/null
@@ -1,607 +0,0 @@
-//===---------------------------- 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:
-// http://www.nongnu.org/libunwind/man/libunwind(3).html
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __LIBUNWIND__
-#define __LIBUNWIND__
-
-#include <__libunwind_config.h>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#ifdef __APPLE__
- #include <Availability.h>
- #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[128];
-};
-typedef struct unw_context_t unw_context_t;
-
-struct unw_cursor_t {
- uint64_t data[140];
-};
-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
- * 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_EBP = 4,
- UNW_X86_ESP = 5,
- UNW_X86_ESI = 6,
- UNW_X86_EDI = 7
-};
-
-// 64-bit x86_64 registers
-enum {
- UNW_X86_64_RAX = 0,
- UNW_X86_64_RDX = 1,
- UNW_X86_64_RCX = 2,
- UNW_X86_64_RBX = 3,
- UNW_X86_64_RSI = 4,
- UNW_X86_64_RDI = 5,
- UNW_X86_64_RBP = 6,
- UNW_X86_64_RSP = 7,
- UNW_X86_64_R8 = 8,
- UNW_X86_64_R9 = 9,
- UNW_X86_64_R10 = 10,
- UNW_X86_64_R11 = 11,
- UNW_X86_64_R12 = 12,
- UNW_X86_64_R13 = 13,
- UNW_X86_64_R14 = 14,
- UNW_X86_64_R15 = 15
-};
-
-
-// 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 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,
-};
-
-// 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,
-};
-
-#endif
Index: contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h
===================================================================
--- contrib/llvm/projects/libunwind/include/mach-o/compact_unwind_encoding.h
+++ /dev/null
@@ -1,478 +0,0 @@
-//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Darwin's alternative to dwarf based unwind encodings.
-//
-//===----------------------------------------------------------------------===//
-
-
-#ifndef __COMPACT_UNWIND_ENCODING__
-#define __COMPACT_UNWIND_ENCODING__
-
-#include <stdint.h>
-
-//
-// Compilers can emit standard Dwarf FDEs in the __TEXT,__eh_frame section
-// of object files. Or compilers can emit compact unwind information in
-// the __LD,__compact_unwind section.
-//
-// When the linker creates a final linked image, it will create a
-// __TEXT,__unwind_info section. This section is a small and fast way for the
-// runtime to access unwind info for any given function. If the compiler
-// emitted compact unwind info for the function, that compact unwind info will
-// be encoded in the __TEXT,__unwind_info section. If the compiler emitted
-// dwarf unwind info, the __TEXT,__unwind_info section will contain the offset
-// of the FDE in the __TEXT,__eh_frame section in the final linked image.
-//
-// Note: Previously, the linker would transform some dwarf unwind infos into
-// compact unwind info. But that is fragile and no longer done.
-
-
-//
-// The compact unwind endoding is a 32-bit value which encoded in an
-// architecture specific way, which registers to restore from where, and how
-// to unwind out of the function.
-//
-typedef uint32_t compact_unwind_encoding_t;
-
-
-// architecture independent bits
-enum {
- UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
- UNWIND_HAS_LSDA = 0x40000000,
- UNWIND_PERSONALITY_MASK = 0x30000000,
-};
-
-
-
-
-//
-// x86
-//
-// 1-bit: start
-// 1-bit: has lsda
-// 2-bit: personality index
-//
-// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf
-// ebp based:
-// 15-bits (5*3-bits per reg) register permutation
-// 8-bits for stack offset
-// frameless:
-// 8-bits stack size
-// 3-bits stack adjust
-// 3-bits register count
-// 10-bits register permutation
-//
-enum {
- UNWIND_X86_MODE_MASK = 0x0F000000,
- UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
- UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
- UNWIND_X86_MODE_STACK_IND = 0x03000000,
- UNWIND_X86_MODE_DWARF = 0x04000000,
-
- UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
- UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
-
- UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
- UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
- UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
- UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
-
- UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
-};
-
-enum {
- UNWIND_X86_REG_NONE = 0,
- UNWIND_X86_REG_EBX = 1,
- UNWIND_X86_REG_ECX = 2,
- UNWIND_X86_REG_EDX = 3,
- UNWIND_X86_REG_EDI = 4,
- UNWIND_X86_REG_ESI = 5,
- UNWIND_X86_REG_EBP = 6,
-};
-
-//
-// For x86 there are four modes for the compact unwind encoding:
-// UNWIND_X86_MODE_EBP_FRAME:
-// EBP based frame where EBP is push on stack immediately after return address,
-// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
-// EPB value, then EBP is restored by popping off the stack, and the return
-// is done by popping the stack once more into the pc.
-// All non-volatile registers that need to be restored must have been saved
-// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4
-// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved
-// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
-// Each entry contains which register to restore.
-// UNWIND_X86_MODE_STACK_IMMD:
-// A "frameless" (EBP not used as frame pointer) function with a small
-// constant stack size. To return, a constant (encoded in the compact
-// unwind encoding) is added to the ESP. Then the return is done by
-// popping the stack into the pc.
-// All non-volatile registers that need to be restored must have been saved
-// on the stack immediately after the return address. The stack_size/4 is
-// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
-// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
-// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
-// saved and their order.
-// UNWIND_X86_MODE_STACK_IND:
-// A "frameless" (EBP not used as frame pointer) function large constant
-// stack size. This case is like the previous, except the stack size is too
-// large to encode in the compact unwind encoding. Instead it requires that
-// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
-// encoding contains the offset to the nnnnnnnn value in the function in
-// UNWIND_X86_FRAMELESS_STACK_SIZE.
-// UNWIND_X86_MODE_DWARF:
-// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
-// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
-// function.
-//
-// The permutation encoding is a Lehmer code sequence encoded into a
-// single variable-base number so we can encode the ordering of up to
-// six registers in a 10-bit space.
-//
-// The following is the algorithm used to create the permutation encoding used
-// with frameless stacks. It is passed the number of registers to be saved and
-// an array of the register numbers saved.
-//
-//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
-//{
-// uint32_t renumregs[6];
-// for (int i=6-registerCount; i < 6; ++i) {
-// int countless = 0;
-// for (int j=6-registerCount; j < i; ++j) {
-// if ( registers[j] < registers[i] )
-// ++countless;
-// }
-// renumregs[i] = registers[i] - countless -1;
-// }
-// uint32_t permutationEncoding = 0;
-// switch ( registerCount ) {
-// case 6:
-// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
-// + 6*renumregs[2] + 2*renumregs[3]
-// + renumregs[4]);
-// break;
-// case 5:
-// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
-// + 6*renumregs[3] + 2*renumregs[4]
-// + renumregs[5]);
-// break;
-// case 4:
-// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
-// + 3*renumregs[4] + renumregs[5]);
-// break;
-// case 3:
-// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
-// + renumregs[5]);
-// break;
-// case 2:
-// permutationEncoding |= (5*renumregs[4] + renumregs[5]);
-// break;
-// case 1:
-// permutationEncoding |= (renumregs[5]);
-// break;
-// }
-// return permutationEncoding;
-//}
-//
-
-
-
-
-//
-// x86_64
-//
-// 1-bit: start
-// 1-bit: has lsda
-// 2-bit: personality index
-//
-// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf
-// rbp based:
-// 15-bits (5*3-bits per reg) register permutation
-// 8-bits for stack offset
-// frameless:
-// 8-bits stack size
-// 3-bits stack adjust
-// 3-bits register count
-// 10-bits register permutation
-//
-enum {
- UNWIND_X86_64_MODE_MASK = 0x0F000000,
- UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
- UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
- UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
- UNWIND_X86_64_MODE_DWARF = 0x04000000,
-
- UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
- UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
-
- UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
- UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
- UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
- UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
-
- UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
-};
-
-enum {
- UNWIND_X86_64_REG_NONE = 0,
- UNWIND_X86_64_REG_RBX = 1,
- UNWIND_X86_64_REG_R12 = 2,
- UNWIND_X86_64_REG_R13 = 3,
- UNWIND_X86_64_REG_R14 = 4,
- UNWIND_X86_64_REG_R15 = 5,
- UNWIND_X86_64_REG_RBP = 6,
-};
-//
-// For x86_64 there are four modes for the compact unwind encoding:
-// UNWIND_X86_64_MODE_RBP_FRAME:
-// RBP based frame where RBP is push on stack immediately after return address,
-// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
-// EPB value, then RBP is restored by popping off the stack, and the return
-// is done by popping the stack once more into the pc.
-// All non-volatile registers that need to be restored must have been saved
-// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
-// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
-// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
-// Each entry contains which register to restore.
-// UNWIND_X86_64_MODE_STACK_IMMD:
-// A "frameless" (RBP not used as frame pointer) function with a small
-// constant stack size. To return, a constant (encoded in the compact
-// unwind encoding) is added to the RSP. Then the return is done by
-// popping the stack into the pc.
-// All non-volatile registers that need to be restored must have been saved
-// on the stack immediately after the return address. The stack_size/8 is
-// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
-// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
-// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
-// saved and their order.
-// UNWIND_X86_64_MODE_STACK_IND:
-// A "frameless" (RBP not used as frame pointer) function large constant
-// stack size. This case is like the previous, except the stack size is too
-// large to encode in the compact unwind encoding. Instead it requires that
-// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
-// encoding contains the offset to the nnnnnnnn value in the function in
-// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
-// UNWIND_X86_64_MODE_DWARF:
-// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
-// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
-// function.
-//
-
-
-// ARM64
-//
-// 1-bit: start
-// 1-bit: has lsda
-// 2-bit: personality index
-//
-// 4-bits: 4=frame-based, 3=dwarf, 2=frameless
-// frameless:
-// 12-bits of stack size
-// frame-based:
-// 4-bits D reg pairs saved
-// 5-bits X reg pairs saved
-// dwarf:
-// 24-bits offset of dwarf FDE in __eh_frame section
-//
-enum {
- UNWIND_ARM64_MODE_MASK = 0x0F000000,
- UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
- UNWIND_ARM64_MODE_DWARF = 0x03000000,
- UNWIND_ARM64_MODE_FRAME = 0x04000000,
-
- UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
- UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
- UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
- UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
- UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
- UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
- UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
- UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
- UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
-
- UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
- UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
-};
-// For arm64 there are three modes for the compact unwind encoding:
-// UNWIND_ARM64_MODE_FRAME:
-// This is a standard arm64 prolog where FP/LR are immediately pushed on the
-// stack, then SP is copied to FP. If there are any non-volatile registers
-// saved, then are copied into the stack frame in pairs in a contiguous
-// range right below the saved FP/LR pair. Any subset of the five X pairs
-// and four D pairs can be saved, but the memory layout must be in register
-// number order.
-// UNWIND_ARM64_MODE_FRAMELESS:
-// A "frameless" leaf function, where FP/LR are not saved. The return address
-// remains in LR throughout the function. If any non-volatile registers
-// are saved, they must be pushed onto the stack before any stack space is
-// allocated for local variables. The stack sized (including any saved
-// non-volatile registers) divided by 16 is encoded in the bits
-// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
-// UNWIND_ARM64_MODE_DWARF:
-// No compact unwind encoding is available. Instead the low 24-bits of the
-// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
-// This mode is never used in object files. It is only generated by the
-// linker in final linked images which have only dwarf unwind info for a
-// function.
-//
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Relocatable Object Files: __LD,__compact_unwind
-//
-////////////////////////////////////////////////////////////////////////////////
-
-//
-// A compiler can generated compact unwind information for a function by adding
-// a "row" to the __LD,__compact_unwind section. This section has the
-// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
-// It is removed by the new linker, so never ends up in final executables.
-// This section is a table, initially with one row per function (that needs
-// unwind info). The table columns and some conceptual entries are:
-//
-// range-start pointer to start of function/range
-// range-length
-// compact-unwind-encoding 32-bit encoding
-// personality-function or zero if no personality function
-// lsda or zero if no LSDA data
-//
-// The length and encoding fields are 32-bits. The other are all pointer sized.
-//
-// In x86_64 assembly, these entry would look like:
-//
-// .section __LD,__compact_unwind,regular,debug
-//
-// #compact unwind for _foo
-// .quad _foo
-// .set L1,LfooEnd-_foo
-// .long L1
-// .long 0x01010001
-// .quad 0
-// .quad 0
-//
-// #compact unwind for _bar
-// .quad _bar
-// .set L2,LbarEnd-_bar
-// .long L2
-// .long 0x01020011
-// .quad __gxx_personality
-// .quad except_tab1
-//
-//
-// Notes: There is no need for any labels in the the __compact_unwind section.
-// The use of the .set directive is to force the evaluation of the
-// range-length at assembly time, instead of generating relocations.
-//
-// To support future compiler optimizations where which non-volatile registers
-// are saved changes within a function (e.g. delay saving non-volatiles until
-// necessary), there can by multiple lines in the __compact_unwind table for one
-// function, each with a different (non-overlapping) range and each with
-// different compact unwind encodings that correspond to the non-volatiles
-// saved at that range of the function.
-//
-// If a particular function is so wacky that there is no compact unwind way
-// to encode it, then the compiler can emit traditional dwarf unwind info.
-// The runtime will use which ever is available.
-//
-// Runtime support for compact unwind encodings are only available on 10.6
-// and later. So, the compiler should not generate it when targeting pre-10.6.
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Final Linked Images: __TEXT,__unwind_info
-//
-////////////////////////////////////////////////////////////////////////////////
-
-//
-// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
-// The header of the section contains a coarse index that maps function address
-// to the page (4096 byte block) containing the unwind info for that function.
-//
-
-#define UNWIND_SECTION_VERSION 1
-struct unwind_info_section_header
-{
- uint32_t version; // UNWIND_SECTION_VERSION
- uint32_t commonEncodingsArraySectionOffset;
- uint32_t commonEncodingsArrayCount;
- uint32_t personalityArraySectionOffset;
- uint32_t personalityArrayCount;
- uint32_t indexSectionOffset;
- uint32_t indexCount;
- // compact_unwind_encoding_t[]
- // uint32_t personalities[]
- // unwind_info_section_header_index_entry[]
- // unwind_info_section_header_lsda_index_entry[]
-};
-
-struct unwind_info_section_header_index_entry
-{
- uint32_t functionOffset;
- uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page
- uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range
-};
-
-struct unwind_info_section_header_lsda_index_entry
-{
- uint32_t functionOffset;
- uint32_t lsdaOffset;
-};
-
-//
-// There are two kinds of second level index pages: regular and compressed.
-// A compressed page can hold up to 1021 entries, but it cannot be used
-// if too many different encoding types are used. The regular page holds
-// 511 entries.
-//
-
-struct unwind_info_regular_second_level_entry
-{
- uint32_t functionOffset;
- compact_unwind_encoding_t encoding;
-};
-
-#define UNWIND_SECOND_LEVEL_REGULAR 2
-struct unwind_info_regular_second_level_page_header
-{
- uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
- uint16_t entryPageOffset;
- uint16_t entryCount;
- // entry array
-};
-
-#define UNWIND_SECOND_LEVEL_COMPRESSED 3
-struct unwind_info_compressed_second_level_page_header
-{
- uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
- uint16_t entryPageOffset;
- uint16_t entryCount;
- uint16_t encodingsPageOffset;
- uint16_t encodingsCount;
- // 32-bit entry array
- // encodings array
-};
-
-#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
-#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
-
-
-
-#endif
-
Index: contrib/llvm/projects/libunwind/include/unwind.h
===================================================================
--- contrib/llvm/projects/libunwind/include/unwind.h
+++ /dev/null
@@ -1,372 +0,0 @@
-//===------------------------------- unwind.h -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// C++ ABI Level 1 ABI documented at:
-// http://mentorembedded.github.io/cxx-abi/abi-eh.html
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __UNWIND_H__
-#define __UNWIND_H__
-
-#include <__libunwind_config.h>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#if defined(__APPLE__)
-#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable ))
-#else
-#define LIBUNWIND_UNAVAIL
-#endif
-
-typedef enum {
- _URC_NO_REASON = 0,
- _URC_OK = 0,
- _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
- _URC_FATAL_PHASE2_ERROR = 2,
- _URC_FATAL_PHASE1_ERROR = 3,
- _URC_NORMAL_STOP = 4,
- _URC_END_OF_STACK = 5,
- _URC_HANDLER_FOUND = 6,
- _URC_INSTALL_CONTEXT = 7,
- _URC_CONTINUE_UNWIND = 8,
-#if _LIBUNWIND_ARM_EHABI
- _URC_FAILURE = 9
-#endif
-} _Unwind_Reason_Code;
-
-typedef enum {
- _UA_SEARCH_PHASE = 1,
- _UA_CLEANUP_PHASE = 2,
- _UA_HANDLER_FRAME = 4,
- _UA_FORCE_UNWIND = 8,
- _UA_END_OF_STACK = 16 // gcc extension to C++ ABI
-} _Unwind_Action;
-
-typedef struct _Unwind_Context _Unwind_Context; // opaque
-
-#if _LIBUNWIND_ARM_EHABI
-typedef uint32_t _Unwind_State;
-
-static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
-static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
-static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
-/* Undocumented flag for force unwinding. */
-static const _Unwind_State _US_FORCE_UNWIND = 8;
-
-typedef uint32_t _Unwind_EHT_Header;
-
-struct _Unwind_Control_Block;
-typedef struct _Unwind_Control_Block _Unwind_Control_Block;
-typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
-
-struct _Unwind_Control_Block {
- uint64_t exception_class;
- void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
-
- /* Unwinder cache, private fields for the unwinder's use */
- struct {
- uint32_t reserved1; /* init reserved1 to 0, then don't touch */
- uint32_t reserved2;
- uint32_t reserved3;
- uint32_t reserved4;
- uint32_t reserved5;
- } unwinder_cache;
-
- /* Propagation barrier cache (valid after phase 1): */
- struct {
- uint32_t sp;
- uint32_t bitpattern[5];
- } barrier_cache;
-
- /* Cleanup cache (preserved over cleanup): */
- struct {
- uint32_t bitpattern[4];
- } cleanup_cache;
-
- /* Pr cache (for pr's benefit): */
- struct {
- uint32_t fnstart; /* function start address */
- _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
- uint32_t additional;
- uint32_t reserved1;
- } pr_cache;
-
- long long int :0; /* Enforce the 8-byte alignment */
-};
-
-typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
- (_Unwind_State state,
- _Unwind_Exception* exceptionObject,
- struct _Unwind_Context* context);
-
-typedef _Unwind_Reason_Code (*__personality_routine)
- (_Unwind_State state,
- _Unwind_Exception* exceptionObject,
- struct _Unwind_Context* context);
-#else
-struct _Unwind_Context; // opaque
-struct _Unwind_Exception; // forward declaration
-typedef struct _Unwind_Exception _Unwind_Exception;
-
-struct _Unwind_Exception {
- uint64_t exception_class;
- void (*exception_cleanup)(_Unwind_Reason_Code reason,
- _Unwind_Exception *exc);
- uintptr_t private_1; // non-zero means forced unwind
- uintptr_t private_2; // holds sp that phase1 found for phase2 to use
-#ifndef __LP64__
- // The gcc implementation of _Unwind_Exception used attribute mode on the
- // above fields which had the side effect of causing this whole struct to
- // round up to 32 bytes in size. To be more explicit, we add pad fields
- // added for binary compatibility.
- uint32_t reserved[3];
-#endif
-};
-
-typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
- (int version,
- _Unwind_Action actions,
- uint64_t exceptionClass,
- _Unwind_Exception* exceptionObject,
- struct _Unwind_Context* context,
- void* stop_parameter );
-
-typedef _Unwind_Reason_Code (*__personality_routine)
- (int version,
- _Unwind_Action actions,
- uint64_t exceptionClass,
- _Unwind_Exception* exceptionObject,
- struct _Unwind_Context* context);
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//
-// The following are the base functions documented by the C++ ABI
-//
-#ifdef __USING_SJLJ_EXCEPTIONS__
-extern _Unwind_Reason_Code
- _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
-extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
-#else
-extern _Unwind_Reason_Code
- _Unwind_RaiseException(_Unwind_Exception *exception_object);
-extern void _Unwind_Resume(_Unwind_Exception *exception_object);
-#endif
-extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
-
-#if _LIBUNWIND_ARM_EHABI
-typedef enum {
- _UVRSC_CORE = 0, /* integer register */
- _UVRSC_VFP = 1, /* vfp */
- _UVRSC_WMMXD = 3, /* Intel WMMX data register */
- _UVRSC_WMMXC = 4 /* Intel WMMX control register */
-} _Unwind_VRS_RegClass;
-
-typedef enum {
- _UVRSD_UINT32 = 0,
- _UVRSD_VFPX = 1,
- _UVRSD_UINT64 = 3,
- _UVRSD_FLOAT = 4,
- _UVRSD_DOUBLE = 5
-} _Unwind_VRS_DataRepresentation;
-
-typedef enum {
- _UVRSR_OK = 0,
- _UVRSR_NOT_IMPLEMENTED = 1,
- _UVRSR_FAILED = 2
-} _Unwind_VRS_Result;
-
-extern void _Unwind_Complete(_Unwind_Exception* exception_object);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep);
-
-extern _Unwind_VRS_Result
-_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
- uint32_t discriminator,
- _Unwind_VRS_DataRepresentation representation);
-#endif
-
-#if !_LIBUNWIND_ARM_EHABI
-
-extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
-extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t new_value);
-extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
-extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
-
-#else // _LIBUNWIND_ARM_EHABI
-
-#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
-#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
-#else
-#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
-#endif
-
-// These are de facto helper functions for ARM, which delegate the function
-// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
-// specification, thus these function MUST be inlined. Please don't replace
-// these with the "extern" function declaration; otherwise, the program
-// including this <unwind.h> header won't be ABI compatible and will result in
-// link error when we are linking the program with libgcc.
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
- uintptr_t value = 0;
- _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
- return value;
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t value) {
- _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
- // remove the thumb-bit before returning
- return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
-}
-
-_LIBUNWIND_EXPORT_UNWIND_LEVEL1
-void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
- uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
- _Unwind_SetGR(context, 15, value | thumb_bit);
-}
-#endif // _LIBUNWIND_ARM_EHABI
-
-extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
-extern uintptr_t
- _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
-#ifdef __USING_SJLJ_EXCEPTIONS__
-extern _Unwind_Reason_Code
- _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object,
- _Unwind_Stop_Fn stop, void *stop_parameter);
-#else
-extern _Unwind_Reason_Code
- _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
- _Unwind_Stop_Fn stop, void *stop_parameter);
-#endif
-
-#ifdef __USING_SJLJ_EXCEPTIONS__
-typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t;
-extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
-extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
-#endif
-
-//
-// The following are semi-suppoted extensions to the C++ ABI
-//
-
-//
-// called by __cxa_rethrow().
-//
-#ifdef __USING_SJLJ_EXCEPTIONS__
-extern _Unwind_Reason_Code
- _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object);
-#else
-extern _Unwind_Reason_Code
- _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object);
-#endif
-
-// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the
-// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack
-// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON.
-typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
- void *);
-extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *);
-
-// _Unwind_GetCFA is a gcc extension that can be called from within a
-// personality handler to get the CFA (stack pointer before call) of
-// current frame.
-extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
-
-
-// _Unwind_GetIPInfo is a gcc extension that can be called from within a
-// personality handler. Similar to _Unwind_GetIP() but also returns in
-// *ipBefore a non-zero value if the instruction pointer is at or before the
-// instruction causing the unwind. Normally, in a function call, the IP returned
-// is the return address which is after the call instruction and may be past the
-// end of the function containing the call instruction.
-extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
- int *ipBefore);
-
-
-// __register_frame() is used with dynamically generated code to register the
-// FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point
-// to its function and optional LSDA.
-// __register_frame() has existed in all versions of Mac OS X, but in 10.4 and
-// 10.5 it was buggy and did not actually register the FDE with the unwinder.
-// In 10.6 and later it does register properly.
-extern void __register_frame(const void *fde);
-extern void __deregister_frame(const void *fde);
-
-// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
-// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind
-// info" which the runtime uses in preference to dwarf unwind info. This
-// function will only work if the target function has an FDE but no compact
-// unwind info.
-struct dwarf_eh_bases {
- uintptr_t tbase;
- uintptr_t dbase;
- uintptr_t func;
-};
-extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
-
-
-// This function attempts to find the start (address of first instruction) of
-// a function given an address inside the function. It only works if the
-// function has an FDE (dwarf unwind info).
-// This function is unimplemented on Mac OS X 10.6 and later. Instead, use
-// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
-extern void *_Unwind_FindEnclosingFunction(void *pc);
-
-// Mac OS X does not support text-rel and data-rel addressing so these functions
-// are unimplemented
-extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
- LIBUNWIND_UNAVAIL;
-extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
- LIBUNWIND_UNAVAIL;
-
-// Mac OS X 10.4 and 10.5 had implementations of these functions in
-// libgcc_s.dylib, but they never worked.
-/// These functions are no longer available on Mac OS X.
-extern void __register_frame_info_bases(const void *fde, void *ob, void *tb,
- void *db) LIBUNWIND_UNAVAIL;
-extern void __register_frame_info(const void *fde, void *ob)
- LIBUNWIND_UNAVAIL;
-extern void __register_frame_info_table_bases(const void *fde, void *ob,
- void *tb, void *db)
- LIBUNWIND_UNAVAIL;
-extern void __register_frame_info_table(const void *fde, void *ob)
- LIBUNWIND_UNAVAIL;
-extern void __register_frame_table(const void *fde)
- LIBUNWIND_UNAVAIL;
-extern void *__deregister_frame_info(const void *fde)
- LIBUNWIND_UNAVAIL;
-extern void *__deregister_frame_info_bases(const void *fde)
- LIBUNWIND_UNAVAIL;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __UNWIND_H__
Index: contrib/llvm/projects/libunwind/src/AddressSpace.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/AddressSpace.hpp
+++ /dev/null
@@ -1,598 +0,0 @@
-//===------------------------- 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 <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef _LIBUNWIND_IS_BAREMETAL
-#include <dlfcn.h>
-#endif
-
-#ifdef __APPLE__
-#include <mach-o/getsect.h>
-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__)
-
-#include <sys/link_elf.h>
-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 <link.h>
-#else // !defined(_LIBUNWIND_IS_BAREMETAL)
-// When statically linked on bare-metal, the symbols for the EH table are looked
-// up without going through the dynamic loader.
-struct EHTEntry {
- uint32_t functionOffset;
- uint32_t unwindOpcodes;
-};
-extern EHTEntry __exidx_start;
-extern EHTEntry __exidx_end;
-#endif // !defined(_LIBUNWIND_IS_BAREMETAL)
-#endif // _LIBUNWIND_ARM_EHABI
-
-#if defined(__CloudABI__) || defined(__FreeBSD__) || defined(__linux__)
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND && _LIBUNWIND_SUPPORT_DWARF_INDEX
-#include <link.h>
-// Macro for machine-independent access to the ELF program headers. This
-// macro is not available on some systems (e.g., FreeBSD). On these
-// systems the data structures are just called Elf_XXX. Define ElfW()
-// locally.
-#if !defined(ElfW)
-#define ElfW(type) Elf_##type
-#endif
-#include "EHHeaderParser.hpp"
-#endif
-#endif
-
-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",
- 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<dl_iterate_cb_data *>(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<LocalAddressSpace>::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<LocalAddressSpace>::decodeEHHdr(
- *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
- hdrInfo);
- cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
- found_hdr = true;
- }
- }
-
- if (found_obj && found_hdr) {
- cbdata->sects->dwarf_section_length = object_length;
- return true;
- } else {
- return false;
- }
- },
- &cb_data);
- return static_cast<bool>(found);
-#else
-#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
-#endif
-#endif
-
- return false;
-}
-
-
-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 <typename P>
-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 <typename P> uint8_t OtherAddressSpace<P>::get8(pint_t addr) {
- return *((uint8_t *)localCopy(addr));
-}
-
-template <typename P> uint16_t OtherAddressSpace<P>::get16(pint_t addr) {
- return P::E::get16(*(uint16_t *)localCopy(addr));
-}
-
-template <typename P> uint32_t OtherAddressSpace<P>::get32(pint_t addr) {
- return P::E::get32(*(uint32_t *)localCopy(addr));
-}
-
-template <typename P> uint64_t OtherAddressSpace<P>::get64(pint_t addr) {
- return P::E::get64(*(uint64_t *)localCopy(addr));
-}
-
-template <typename P>
-typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) {
- return P::getP(*(uint64_t *)localCopy(addr));
-}
-
-template <typename P>
-uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
- uintptr_t size = (end - addr);
- LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
- LocalAddressSpace::pint_t sladdr = laddr;
- uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
- addr += (laddr - sladdr);
- return result;
-}
-
-template <typename P>
-int64_t OtherAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
- uintptr_t size = (end - addr);
- LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
- LocalAddressSpace::pint_t sladdr = laddr;
- uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
- addr += (laddr - sladdr);
- return result;
-}
-
-template <typename P> void *OtherAddressSpace<P>::localCopy(pint_t addr) {
- // FIX ME
-}
-
-template <typename P>
-bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
- size_t bufLen, unw_word_t *offset) {
- // 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<Pointer32<LittleEndian> > oas;
-};
-
-/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
-/// points to when examining
-/// a 64-bit intel process.
-struct unw_addr_space_x86_64 : public unw_addr_space {
- unw_addr_space_x86_64(task_t task) : oas(task) {}
- OtherAddressSpace<Pointer64<LittleEndian> > oas;
-};
-
-/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
-/// to when examining
-/// a 32-bit PowerPC process.
-struct unw_addr_space_ppc : public unw_addr_space {
- unw_addr_space_ppc(task_t task) : oas(task) {}
- OtherAddressSpace<Pointer32<BigEndian> > oas;
-};
-
-#endif // UNW_REMOTE
-
-} // namespace libunwind
-
-#endif // __ADDRESSSPACE_HPP__
Index: contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/CompactUnwinder.hpp
+++ /dev/null
@@ -1,693 +0,0 @@
-//===-------------------------- 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 <stdint.h>
-#include <stdlib.h>
-
-#include <libunwind.h>
-#include <mach-o/compact_unwind_encoding.h>
-
-#include "AddressSpace.hpp"
-#include "Registers.hpp"
-
-#define EXTRACT_BITS(value, mask) \
- ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))
-
-namespace libunwind {
-
-/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka
-/// unwind) by modifying a Registers_x86 register set
-template <typename A>
-class CompactUnwinder_x86 {
-public:
-
- static int stepWithCompactEncoding(compact_unwind_encoding_t info,
- uint32_t functionStart, A &addressSpace,
- Registers_x86 &registers);
-
-private:
- typename A::pint_t pint_t;
-
- static void frameUnwind(A &addressSpace, Registers_x86 &registers);
- static void framelessUnwind(A &addressSpace,
- typename A::pint_t returnAddressLocation,
- Registers_x86 &registers);
- static int
- stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding,
- uint32_t functionStart, A &addressSpace,
- Registers_x86 &registers);
- static int stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
- A &addressSpace, Registers_x86 &registers, bool indirectStackSize);
-};
-
-template <typename A>
-int CompactUnwinder_x86<A>::stepWithCompactEncoding(
- compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
- A &addressSpace, Registers_x86 &registers) {
- 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 <typename A>
-int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(
- compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
- A &addressSpace, Registers_x86 &registers) {
- 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",
- compactEncoding, functionStart);
- _LIBUNWIND_ABORT("invalid compact unwind encoding");
- }
- savedRegisters += 4;
- savedRegistersLocations = (savedRegistersLocations >> 3);
- }
- frameUnwind(addressSpace, registers);
- return UNW_STEP_SUCCESS;
-}
-
-template <typename A>
-int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t encoding, uint32_t functionStart,
- A &addressSpace, Registers_x86 &registers, 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",
- encoding, functionStart);
- _LIBUNWIND_ABORT("invalid compact unwind encoding");
- }
- savedRegisters += 4;
- }
- framelessUnwind(addressSpace, savedRegisters, registers);
- return UNW_STEP_SUCCESS;
-}
-
-
-template <typename A>
-void CompactUnwinder_x86<A>::frameUnwind(A &addressSpace,
- Registers_x86 &registers) {
- 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 <typename A>
-void CompactUnwinder_x86<A>::framelessUnwind(
- A &addressSpace, typename A::pint_t returnAddressLocation,
- Registers_x86 &registers) {
- // 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);
-}
-
-
-/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka
-/// unwind) by modifying a Registers_x86_64 register set
-template <typename A>
-class CompactUnwinder_x86_64 {
-public:
-
- static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
- uint64_t functionStart, A &addressSpace,
- Registers_x86_64 &registers);
-
-private:
- typename A::pint_t pint_t;
-
- static void frameUnwind(A &addressSpace, Registers_x86_64 &registers);
- static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation,
- Registers_x86_64 &registers);
- static int
- stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding,
- uint64_t functionStart, A &addressSpace,
- Registers_x86_64 &registers);
- static int stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
- A &addressSpace, Registers_x86_64 &registers, bool indirectStackSize);
-};
-
-template <typename A>
-int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
- compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
- A &addressSpace, Registers_x86_64 &registers) {
- 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 <typename A>
-int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
- compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
- A &addressSpace, Registers_x86_64 &registers) {
- 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",
- compactEncoding, functionStart);
- _LIBUNWIND_ABORT("invalid compact unwind encoding");
- }
- savedRegisters += 8;
- savedRegistersLocations = (savedRegistersLocations >> 3);
- }
- frameUnwind(addressSpace, registers);
- return UNW_STEP_SUCCESS;
-}
-
-template <typename A>
-int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace,
- Registers_x86_64 &registers, 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",
- encoding, functionStart);
- _LIBUNWIND_ABORT("invalid compact unwind encoding");
- }
- savedRegisters += 8;
- }
- framelessUnwind(addressSpace, savedRegisters, registers);
- return UNW_STEP_SUCCESS;
-}
-
-
-template <typename A>
-void CompactUnwinder_x86_64<A>::frameUnwind(A &addressSpace,
- Registers_x86_64 &registers) {
- 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 <typename A>
-void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,
- uint64_t returnAddressLocation,
- Registers_x86_64 &registers) {
- // return address is on stack after last saved register
- registers.setIP(addressSpace.get64(returnAddressLocation));
- // old esp is before return address
- registers.setSP(returnAddressLocation + 8);
-}
-
-
-
-/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka
-/// unwind) by modifying a Registers_arm64 register set
-template <typename A>
-class CompactUnwinder_arm64 {
-public:
-
- static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
- uint64_t functionStart, A &addressSpace,
- Registers_arm64 &registers);
-
-private:
- typename A::pint_t pint_t;
-
- static int
- stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding,
- uint64_t functionStart, A &addressSpace,
- Registers_arm64 &registers);
- static int stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
- A &addressSpace, Registers_arm64 &registers);
-};
-
-template <typename A>
-int CompactUnwinder_arm64<A>::stepWithCompactEncoding(
- compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
- A &addressSpace, Registers_arm64 &registers) {
- 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 <typename A>
-int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(
- compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
- Registers_arm64 &registers) {
- 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 <typename A>
-int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
- compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
- Registers_arm64 &registers) {
- 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;
-}
-
-
-} // namespace libunwind
-
-#endif // __COMPACT_UNWINDER_HPP__
Index: contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp
+++ /dev/null
@@ -1,760 +0,0 @@
-//===-------------------------- DwarfInstructions.hpp ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Processor specific interpretation of dwarf unwind info.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __DWARF_INSTRUCTIONS_HPP__
-#define __DWARF_INSTRUCTIONS_HPP__
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "dwarf2.h"
-#include "AddressSpace.hpp"
-#include "Registers.hpp"
-#include "DwarfParser.hpp"
-#include "config.h"
-
-
-namespace libunwind {
-
-
-/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
-/// architecture
-template <typename A, typename R>
-class DwarfInstructions {
-public:
- typedef typename A::pint_t pint_t;
- typedef typename A::sint_t sint_t;
-
- static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
- R &registers);
-
-private:
-
- enum {
- DW_X86_64_RET_ADDR = 16
- };
-
- enum {
- DW_X86_RET_ADDR = 8
- };
-
- typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
- typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
- typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
- typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
-
- static pint_t evaluateExpression(pint_t expression, A &addressSpace,
- const R &registers,
- pint_t initialStackValue);
- static pint_t getSavedRegister(A &addressSpace, const R &registers,
- pint_t cfa, const RegisterLocation &savedReg);
- static double getSavedFloatRegister(A &addressSpace, const R &registers,
- pint_t cfa, const RegisterLocation &savedReg);
- static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
- pint_t cfa, const RegisterLocation &savedReg);
-
- static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
- const R &registers) {
- if (prolog.cfaRegister != 0)
- return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
- prolog.cfaRegisterOffset);
- if (prolog.cfaExpression != 0)
- return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
- registers, 0);
- assert(0 && "getCFA(): unknown location");
- __builtin_unreachable();
- }
-};
-
-
-template <typename A, typename R>
-typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
- A &addressSpace, const R &registers, pint_t cfa,
- const RegisterLocation &savedReg) {
- switch (savedReg.location) {
- case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getP(cfa + (pint_t)savedReg.value);
-
- case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getP(
- evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa));
-
- case CFI_Parser<A>::kRegisterIsExpression:
- return evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa);
-
- case CFI_Parser<A>::kRegisterInRegister:
- return registers.getRegister((int)savedReg.value);
-
- case CFI_Parser<A>::kRegisterUnused:
- case CFI_Parser<A>::kRegisterOffsetFromCFA:
- // FIX ME
- break;
- }
- _LIBUNWIND_ABORT("unsupported restore location for register");
-}
-
-template <typename A, typename R>
-double DwarfInstructions<A, R>::getSavedFloatRegister(
- A &addressSpace, const R &registers, pint_t cfa,
- const RegisterLocation &savedReg) {
- switch (savedReg.location) {
- case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
-
- case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getDouble(
- evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa));
-
- case CFI_Parser<A>::kRegisterIsExpression:
- case CFI_Parser<A>::kRegisterUnused:
- case CFI_Parser<A>::kRegisterOffsetFromCFA:
- case CFI_Parser<A>::kRegisterInRegister:
- // FIX ME
- break;
- }
- _LIBUNWIND_ABORT("unsupported restore location for float register");
-}
-
-template <typename A, typename R>
-v128 DwarfInstructions<A, R>::getSavedVectorRegister(
- A &addressSpace, const R &registers, pint_t cfa,
- const RegisterLocation &savedReg) {
- switch (savedReg.location) {
- case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getVector(cfa + (pint_t)savedReg.value);
-
- case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getVector(
- evaluateExpression((pint_t)savedReg.value, addressSpace,
- registers, cfa));
-
- case CFI_Parser<A>::kRegisterIsExpression:
- case CFI_Parser<A>::kRegisterUnused:
- case CFI_Parser<A>::kRegisterOffsetFromCFA:
- case CFI_Parser<A>::kRegisterInRegister:
- // FIX ME
- break;
- }
- _LIBUNWIND_ABORT("unsupported restore location for vector register");
-}
-
-template <typename A, typename R>
-int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
- pint_t fdeStart, R &registers) {
- FDE_Info fdeInfo;
- CIE_Info cieInfo;
- if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
- &cieInfo) == NULL) {
- PrologInfo prolog;
- if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
- &prolog)) {
- // get pointer to cfa (architecture specific)
- pint_t cfa = getCFA(addressSpace, prolog, registers);
-
- // restore registers that dwarf says were saved
- R newRegisters = registers;
- pint_t returnAddress = 0;
- const int lastReg = R::lastDwarfRegNum();
- assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg &&
- "register range too large");
- assert(lastReg >= (int)cieInfo.returnAddressRegister &&
- "register range does not contain return address register");
- for (int i = 0; i <= lastReg; ++i) {
- if (prolog.savedRegisters[i].location !=
- CFI_Parser<A>::kRegisterUnused) {
- if (registers.validFloatRegister(i))
- newRegisters.setFloatRegister(
- i, getSavedFloatRegister(addressSpace, registers, cfa,
- prolog.savedRegisters[i]));
- else if (registers.validVectorRegister(i))
- newRegisters.setVectorRegister(
- i, getSavedVectorRegister(addressSpace, registers, cfa,
- prolog.savedRegisters[i]));
- else if (i == (int)cieInfo.returnAddressRegister)
- returnAddress = getSavedRegister(addressSpace, registers, cfa,
- prolog.savedRegisters[i]);
- else if (registers.validRegister(i))
- newRegisters.setRegister(
- i, getSavedRegister(addressSpace, registers, cfa,
- prolog.savedRegisters[i]));
- else
- return UNW_EBADREG;
- }
- }
-
- // By definition, the CFA is the stack pointer at the call site, so
- // restoring SP means setting it to CFA.
- newRegisters.setSP(cfa);
-
- // Return address is address after call site instruction, so setting IP to
- // that does simualates a return.
- newRegisters.setIP(returnAddress);
-
- // Simulate the step by replacing the register set with the new ones.
- registers = newRegisters;
-
- return UNW_STEP_SUCCESS;
- }
- }
- return UNW_EBADFRAME;
-}
-
-template <typename A, typename R>
-typename A::pint_t
-DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
- const R &registers,
- pint_t initialStackValue) {
- const bool log = false;
- pint_t p = expression;
- pint_t expressionEnd = expression + 20; // temp, until len read
- pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
- expressionEnd = p + length;
- if (log)
- fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
- (uint64_t)length);
- pint_t stack[100];
- pint_t *sp = stack;
- *(++sp) = initialStackValue;
-
- while (p < expressionEnd) {
- if (log) {
- for (pint_t *t = sp; t > stack; --t) {
- fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
- }
- }
- uint8_t opcode = addressSpace.get8(p++);
- sint_t svalue, svalue2;
- pint_t value;
- uint32_t reg;
- switch (opcode) {
- case DW_OP_addr:
- // push immediate address sized value
- value = addressSpace.getP(p);
- p += sizeof(pint_t);
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_deref:
- // pop stack, dereference, push result
- value = *sp--;
- *(++sp) = addressSpace.getP(value);
- if (log)
- fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_const1u:
- // push immediate 1 byte value
- value = addressSpace.get8(p);
- p += 1;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_const1s:
- // push immediate 1 byte signed value
- svalue = (int8_t) addressSpace.get8(p);
- p += 1;
- *(++sp) = (pint_t)svalue;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_const2u:
- // push immediate 2 byte value
- value = addressSpace.get16(p);
- p += 2;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_const2s:
- // push immediate 2 byte signed value
- svalue = (int16_t) addressSpace.get16(p);
- p += 2;
- *(++sp) = (pint_t)svalue;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_const4u:
- // push immediate 4 byte value
- value = addressSpace.get32(p);
- p += 4;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_const4s:
- // push immediate 4 byte signed value
- svalue = (int32_t)addressSpace.get32(p);
- p += 4;
- *(++sp) = (pint_t)svalue;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_const8u:
- // push immediate 8 byte value
- value = (pint_t)addressSpace.get64(p);
- p += 8;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_const8s:
- // push immediate 8 byte signed value
- value = (pint_t)addressSpace.get64(p);
- p += 8;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_constu:
- // push immediate ULEB128 value
- value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_consts:
- // push immediate SLEB128 value
- svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
- *(++sp) = (pint_t)svalue;
- if (log)
- fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_dup:
- // push top of stack
- value = *sp;
- *(++sp) = value;
- if (log)
- fprintf(stderr, "duplicate top of stack\n");
- break;
-
- case DW_OP_drop:
- // pop
- --sp;
- if (log)
- fprintf(stderr, "pop top of stack\n");
- break;
-
- case DW_OP_over:
- // dup second
- value = sp[-1];
- *(++sp) = value;
- if (log)
- fprintf(stderr, "duplicate second in stack\n");
- break;
-
- case DW_OP_pick:
- // pick from
- reg = addressSpace.get8(p);
- p += 1;
- value = sp[-reg];
- *(++sp) = value;
- if (log)
- fprintf(stderr, "duplicate %d in stack\n", reg);
- break;
-
- case DW_OP_swap:
- // swap top two
- value = sp[0];
- sp[0] = sp[-1];
- sp[-1] = value;
- if (log)
- fprintf(stderr, "swap top of stack\n");
- break;
-
- case DW_OP_rot:
- // rotate top three
- value = sp[0];
- sp[0] = sp[-1];
- sp[-1] = sp[-2];
- sp[-2] = value;
- if (log)
- fprintf(stderr, "rotate top three of stack\n");
- break;
-
- case DW_OP_xderef:
- // pop stack, dereference, push result
- value = *sp--;
- *sp = *((pint_t*)value);
- if (log)
- fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_abs:
- svalue = (sint_t)*sp;
- if (svalue < 0)
- *sp = (pint_t)(-svalue);
- if (log)
- fprintf(stderr, "abs\n");
- break;
-
- case DW_OP_and:
- value = *sp--;
- *sp &= value;
- if (log)
- fprintf(stderr, "and\n");
- break;
-
- case DW_OP_div:
- svalue = (sint_t)(*sp--);
- svalue2 = (sint_t)*sp;
- *sp = (pint_t)(svalue2 / svalue);
- if (log)
- fprintf(stderr, "div\n");
- break;
-
- case DW_OP_minus:
- value = *sp--;
- *sp = *sp - value;
- if (log)
- fprintf(stderr, "minus\n");
- break;
-
- case DW_OP_mod:
- svalue = (sint_t)(*sp--);
- svalue2 = (sint_t)*sp;
- *sp = (pint_t)(svalue2 % svalue);
- if (log)
- fprintf(stderr, "module\n");
- break;
-
- case DW_OP_mul:
- svalue = (sint_t)(*sp--);
- svalue2 = (sint_t)*sp;
- *sp = (pint_t)(svalue2 * svalue);
- if (log)
- fprintf(stderr, "mul\n");
- break;
-
- case DW_OP_neg:
- *sp = 0 - *sp;
- if (log)
- fprintf(stderr, "neg\n");
- break;
-
- case DW_OP_not:
- svalue = (sint_t)(*sp);
- *sp = (pint_t)(~svalue);
- if (log)
- fprintf(stderr, "not\n");
- break;
-
- case DW_OP_or:
- value = *sp--;
- *sp |= value;
- if (log)
- fprintf(stderr, "or\n");
- break;
-
- case DW_OP_plus:
- value = *sp--;
- *sp += value;
- if (log)
- fprintf(stderr, "plus\n");
- break;
-
- case DW_OP_plus_uconst:
- // pop stack, add uelb128 constant, push result
- *sp += addressSpace.getULEB128(p, expressionEnd);
- if (log)
- fprintf(stderr, "add constant\n");
- break;
-
- case DW_OP_shl:
- value = *sp--;
- *sp = *sp << value;
- if (log)
- fprintf(stderr, "shift left\n");
- break;
-
- case DW_OP_shr:
- value = *sp--;
- *sp = *sp >> value;
- if (log)
- fprintf(stderr, "shift left\n");
- break;
-
- case DW_OP_shra:
- value = *sp--;
- svalue = (sint_t)*sp;
- *sp = (pint_t)(svalue >> value);
- if (log)
- fprintf(stderr, "shift left arithmetric\n");
- break;
-
- case DW_OP_xor:
- value = *sp--;
- *sp ^= value;
- if (log)
- fprintf(stderr, "xor\n");
- break;
-
- case DW_OP_skip:
- svalue = (int16_t) addressSpace.get16(p);
- p += 2;
- p = (pint_t)((sint_t)p + svalue);
- if (log)
- fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_bra:
- svalue = (int16_t) addressSpace.get16(p);
- p += 2;
- if (*sp--)
- p = (pint_t)((sint_t)p + svalue);
- if (log)
- fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
- break;
-
- case DW_OP_eq:
- value = *sp--;
- *sp = (*sp == value);
- if (log)
- fprintf(stderr, "eq\n");
- break;
-
- case DW_OP_ge:
- value = *sp--;
- *sp = (*sp >= value);
- if (log)
- fprintf(stderr, "ge\n");
- break;
-
- case DW_OP_gt:
- value = *sp--;
- *sp = (*sp > value);
- if (log)
- fprintf(stderr, "gt\n");
- break;
-
- case DW_OP_le:
- value = *sp--;
- *sp = (*sp <= value);
- if (log)
- fprintf(stderr, "le\n");
- break;
-
- case DW_OP_lt:
- value = *sp--;
- *sp = (*sp < value);
- if (log)
- fprintf(stderr, "lt\n");
- break;
-
- case DW_OP_ne:
- value = *sp--;
- *sp = (*sp != value);
- if (log)
- fprintf(stderr, "ne\n");
- break;
-
- case DW_OP_lit0:
- case DW_OP_lit1:
- case DW_OP_lit2:
- case DW_OP_lit3:
- case DW_OP_lit4:
- case DW_OP_lit5:
- case DW_OP_lit6:
- case DW_OP_lit7:
- case DW_OP_lit8:
- case DW_OP_lit9:
- case DW_OP_lit10:
- case DW_OP_lit11:
- case DW_OP_lit12:
- case DW_OP_lit13:
- case DW_OP_lit14:
- case DW_OP_lit15:
- case DW_OP_lit16:
- case DW_OP_lit17:
- case DW_OP_lit18:
- case DW_OP_lit19:
- case DW_OP_lit20:
- case DW_OP_lit21:
- case DW_OP_lit22:
- case DW_OP_lit23:
- case DW_OP_lit24:
- case DW_OP_lit25:
- case DW_OP_lit26:
- case DW_OP_lit27:
- case DW_OP_lit28:
- case DW_OP_lit29:
- case DW_OP_lit30:
- case DW_OP_lit31:
- value = static_cast<pint_t>(opcode - DW_OP_lit0);
- *(++sp) = value;
- if (log)
- fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_reg0:
- case DW_OP_reg1:
- case DW_OP_reg2:
- case DW_OP_reg3:
- case DW_OP_reg4:
- case DW_OP_reg5:
- case DW_OP_reg6:
- case DW_OP_reg7:
- case DW_OP_reg8:
- case DW_OP_reg9:
- case DW_OP_reg10:
- case DW_OP_reg11:
- case DW_OP_reg12:
- case DW_OP_reg13:
- case DW_OP_reg14:
- case DW_OP_reg15:
- case DW_OP_reg16:
- case DW_OP_reg17:
- case DW_OP_reg18:
- case DW_OP_reg19:
- case DW_OP_reg20:
- case DW_OP_reg21:
- case DW_OP_reg22:
- case DW_OP_reg23:
- case DW_OP_reg24:
- case DW_OP_reg25:
- case DW_OP_reg26:
- case DW_OP_reg27:
- case DW_OP_reg28:
- case DW_OP_reg29:
- case DW_OP_reg30:
- case DW_OP_reg31:
- reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
- *(++sp) = registers.getRegister((int)reg);
- if (log)
- fprintf(stderr, "push reg %d\n", reg);
- break;
-
- case DW_OP_regx:
- reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
- *(++sp) = registers.getRegister((int)reg);
- if (log)
- fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
- break;
-
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
- svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
- svalue += static_cast<sint_t>(registers.getRegister((int)reg));
- *(++sp) = (pint_t)(svalue);
- if (log)
- fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
- break;
-
- case DW_OP_bregx:
- reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
- svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
- svalue += static_cast<sint_t>(registers.getRegister((int)reg));
- *(++sp) = (pint_t)(svalue);
- if (log)
- fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
- break;
-
- case DW_OP_fbreg:
- _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
- break;
-
- case DW_OP_piece:
- _LIBUNWIND_ABORT("DW_OP_piece not implemented");
- break;
-
- case DW_OP_deref_size:
- // pop stack, dereference, push result
- value = *sp--;
- switch (addressSpace.get8(p++)) {
- case 1:
- value = addressSpace.get8(value);
- break;
- case 2:
- value = addressSpace.get16(value);
- break;
- case 4:
- value = addressSpace.get32(value);
- break;
- case 8:
- value = (pint_t)addressSpace.get64(value);
- break;
- default:
- _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
- }
- *(++sp) = value;
- if (log)
- fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
- break;
-
- case DW_OP_xderef_size:
- case DW_OP_nop:
- case DW_OP_push_object_addres:
- case DW_OP_call2:
- case DW_OP_call4:
- case DW_OP_call_ref:
- default:
- _LIBUNWIND_ABORT("dwarf opcode not implemented");
- }
-
- }
- if (log)
- fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
- return *sp;
-}
-
-
-
-} // namespace libunwind
-
-#endif // __DWARF_INSTRUCTIONS_HPP__
Index: contrib/llvm/projects/libunwind/src/DwarfParser.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/DwarfParser.hpp
+++ /dev/null
@@ -1,726 +0,0 @@
-//===--------------------------- DwarfParser.hpp --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Parses DWARF CFIs (FDEs and CIEs).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __DWARF_PARSER_HPP__
-#define __DWARF_PARSER_HPP__
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "libunwind.h"
-#include "dwarf2.h"
-
-#include "AddressSpace.hpp"
-
-namespace libunwind {
-
-/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
-/// See Dwarf Spec for details:
-/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
-///
-template <typename A>
-class CFI_Parser {
-public:
- typedef typename A::pint_t pint_t;
-
- /// Information encoded in a CIE (Common Information Entry)
- struct CIE_Info {
- pint_t cieStart;
- pint_t cieLength;
- pint_t cieInstructions;
- uint8_t pointerEncoding;
- uint8_t lsdaEncoding;
- uint8_t personalityEncoding;
- uint8_t personalityOffsetInCIE;
- pint_t personality;
- uint32_t codeAlignFactor;
- int dataAlignFactor;
- bool isSignalFrame;
- bool fdesHaveAugmentationData;
- uint8_t returnAddressRegister;
- };
-
- /// Information about an FDE (Frame Description Entry)
- struct FDE_Info {
- pint_t fdeStart;
- pint_t fdeLength;
- pint_t fdeInstructions;
- pint_t pcStart;
- pint_t pcEnd;
- pint_t lsda;
- };
-
- enum {
- kMaxRegisterNumber = 120
- };
- enum RegisterSavedWhere {
- kRegisterUnused,
- kRegisterInCFA,
- kRegisterOffsetFromCFA,
- kRegisterInRegister,
- kRegisterAtExpression,
- kRegisterIsExpression
- };
- struct RegisterLocation {
- RegisterSavedWhere location;
- int64_t value;
- };
- /// Information about a frame layout and registers saved determined
- /// by "running" the dwarf FDE "instructions"
- struct PrologInfo {
- uint32_t cfaRegister;
- int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
- int64_t cfaExpression; // CFA = expression
- uint32_t spExtraArgSize;
- uint32_t codeOffsetAtStackDecrement;
- bool registersInOtherRegisters;
- bool sameValueUsed;
- RegisterLocation savedRegisters[kMaxRegisterNumber];
- };
-
- struct PrologInfoStackEntry {
- PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
- : next(n), info(i) {}
- PrologInfoStackEntry *next;
- PrologInfo info;
- };
-
- static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
- uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
- CIE_Info *cieInfo);
- static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
- FDE_Info *fdeInfo, CIE_Info *cieInfo);
- static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
- const CIE_Info &cieInfo, pint_t upToPC,
- PrologInfo *results);
-
- static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
-
-private:
- static bool parseInstructions(A &addressSpace, pint_t instructions,
- pint_t instructionsEnd, const CIE_Info &cieInfo,
- pint_t pcoffset,
- PrologInfoStackEntry *&rememberStack,
- PrologInfo *results);
-};
-
-/// Parse a FDE into a CIE_Info and an FDE_Info
-template <typename A>
-const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
- FDE_Info *fdeInfo, CIE_Info *cieInfo) {
- pint_t p = fdeStart;
- pint_t cfiLength = (pint_t)addressSpace.get32(p);
- p += 4;
- if (cfiLength == 0xffffffff) {
- // 0xffffffff means length is really next 8 bytes
- cfiLength = (pint_t)addressSpace.get64(p);
- p += 8;
- }
- if (cfiLength == 0)
- return "FDE has zero length"; // end marker
- uint32_t ciePointer = addressSpace.get32(p);
- if (ciePointer == 0)
- return "FDE is really a CIE"; // this is a CIE not an FDE
- pint_t nextCFI = p + cfiLength;
- pint_t cieStart = p - ciePointer;
- const char *err = parseCIE(addressSpace, cieStart, cieInfo);
- if (err != NULL)
- return err;
- p += 4;
- // parse pc begin and range
- pint_t pcStart =
- addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
- pint_t pcRange =
- addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
- // parse rest of info
- fdeInfo->lsda = 0;
- // check for augmentation length
- if (cieInfo->fdesHaveAugmentationData) {
- pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
- pint_t endOfAug = p + augLen;
- if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
- // peek at value (without indirection). Zero means no lsda
- pint_t lsdaStart = p;
- if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
- 0) {
- // reset pointer and re-parse lsda address
- p = lsdaStart;
- fdeInfo->lsda =
- addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
- }
- }
- p = endOfAug;
- }
- fdeInfo->fdeStart = fdeStart;
- fdeInfo->fdeLength = nextCFI - fdeStart;
- fdeInfo->fdeInstructions = p;
- fdeInfo->pcStart = pcStart;
- fdeInfo->pcEnd = pcStart + pcRange;
- return NULL; // success
-}
-
-/// Scan an eh_frame section to find an FDE for a pc
-template <typename A>
-bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
- uint32_t sectionLength, pint_t fdeHint,
- FDE_Info *fdeInfo, CIE_Info *cieInfo) {
- //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
- pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
- const pint_t ehSectionEnd = p + sectionLength;
- while (p < ehSectionEnd) {
- pint_t currentCFI = p;
- //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
- pint_t cfiLength = addressSpace.get32(p);
- p += 4;
- if (cfiLength == 0xffffffff) {
- // 0xffffffff means length is really next 8 bytes
- cfiLength = (pint_t)addressSpace.get64(p);
- p += 8;
- }
- if (cfiLength == 0)
- return false; // end marker
- uint32_t id = addressSpace.get32(p);
- if (id == 0) {
- // skip over CIEs
- p += cfiLength;
- } else {
- // process FDE to see if it covers pc
- pint_t nextCFI = p + cfiLength;
- uint32_t ciePointer = addressSpace.get32(p);
- pint_t cieStart = p - ciePointer;
- // validate pointer to CIE is within section
- if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
- if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
- p += 4;
- // parse pc begin and range
- pint_t pcStart =
- addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
- pint_t pcRange = addressSpace.getEncodedP(
- p, nextCFI, cieInfo->pointerEncoding & 0x0F);
- // test if pc is within the function this FDE covers
- if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
- // parse rest of info
- fdeInfo->lsda = 0;
- // check for augmentation length
- if (cieInfo->fdesHaveAugmentationData) {
- pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
- pint_t endOfAug = p + augLen;
- if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
- // peek at value (without indirection). Zero means no lsda
- pint_t lsdaStart = p;
- if (addressSpace.getEncodedP(
- p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
- // reset pointer and re-parse lsda address
- p = lsdaStart;
- fdeInfo->lsda = addressSpace
- .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
- }
- }
- p = endOfAug;
- }
- fdeInfo->fdeStart = currentCFI;
- fdeInfo->fdeLength = nextCFI - currentCFI;
- fdeInfo->fdeInstructions = p;
- fdeInfo->pcStart = pcStart;
- fdeInfo->pcEnd = pcStart + pcRange;
- return true;
- } else {
- // pc is not in begin/range, skip this FDE
- }
- } else {
- // malformed CIE, now augmentation describing pc range encoding
- }
- } else {
- // malformed FDE. CIE is bad
- }
- p = nextCFI;
- }
- }
- return false;
-}
-
-/// Extract info from a CIE
-template <typename A>
-const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
- CIE_Info *cieInfo) {
- cieInfo->pointerEncoding = 0;
- cieInfo->lsdaEncoding = DW_EH_PE_omit;
- cieInfo->personalityEncoding = 0;
- cieInfo->personalityOffsetInCIE = 0;
- cieInfo->personality = 0;
- cieInfo->codeAlignFactor = 0;
- cieInfo->dataAlignFactor = 0;
- cieInfo->isSignalFrame = false;
- cieInfo->fdesHaveAugmentationData = false;
- cieInfo->cieStart = cie;
- pint_t p = cie;
- pint_t cieLength = (pint_t)addressSpace.get32(p);
- p += 4;
- pint_t cieContentEnd = p + cieLength;
- if (cieLength == 0xffffffff) {
- // 0xffffffff means length is really next 8 bytes
- cieLength = (pint_t)addressSpace.get64(p);
- p += 8;
- cieContentEnd = p + cieLength;
- }
- if (cieLength == 0)
- return NULL;
- // CIE ID is always 0
- if (addressSpace.get32(p) != 0)
- return "CIE ID is not zero";
- p += 4;
- // Version is always 1 or 3
- uint8_t version = addressSpace.get8(p);
- if ((version != 1) && (version != 3))
- return "CIE version is not 1 or 3";
- ++p;
- // save start of augmentation string and find end
- pint_t strStart = p;
- while (addressSpace.get8(p) != 0)
- ++p;
- ++p;
- // parse code aligment factor
- cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
- // parse data alignment factor
- cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
- // parse return address register
- uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
- assert(raReg < 255 && "return address register too large");
- cieInfo->returnAddressRegister = (uint8_t)raReg;
- // parse augmentation data based on augmentation string
- const char *result = NULL;
- if (addressSpace.get8(strStart) == 'z') {
- // parse augmentation data length
- addressSpace.getULEB128(p, cieContentEnd);
- for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
- switch (addressSpace.get8(s)) {
- case 'z':
- cieInfo->fdesHaveAugmentationData = true;
- break;
- case 'P':
- cieInfo->personalityEncoding = addressSpace.get8(p);
- ++p;
- cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
- cieInfo->personality = addressSpace
- .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
- break;
- case 'L':
- cieInfo->lsdaEncoding = addressSpace.get8(p);
- ++p;
- break;
- case 'R':
- cieInfo->pointerEncoding = addressSpace.get8(p);
- ++p;
- break;
- case 'S':
- cieInfo->isSignalFrame = true;
- break;
- default:
- // ignore unknown letters
- break;
- }
- }
- }
- cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
- cieInfo->cieInstructions = p;
- return result;
-}
-
-
-/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
-template <typename A>
-bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
- const FDE_Info &fdeInfo,
- const CIE_Info &cieInfo, pint_t upToPC,
- PrologInfo *results) {
- // clear results
- memset(results, '\0', sizeof(PrologInfo));
- PrologInfoStackEntry *rememberStack = NULL;
-
- // parse CIE then FDE instructions
- return parseInstructions(addressSpace, cieInfo.cieInstructions,
- cieInfo.cieStart + cieInfo.cieLength, cieInfo,
- (pint_t)(-1), rememberStack, results) &&
- parseInstructions(addressSpace, fdeInfo.fdeInstructions,
- fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
- upToPC - fdeInfo.pcStart, rememberStack, results);
-}
-
-/// "run" the dwarf instructions
-template <typename A>
-bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
- pint_t instructionsEnd,
- const CIE_Info &cieInfo, pint_t pcoffset,
- PrologInfoStackEntry *&rememberStack,
- PrologInfo *results) {
- const bool logDwarf = false;
- pint_t p = instructions;
- pint_t codeOffset = 0;
- PrologInfo initialState = *results;
- if (logDwarf)
- fprintf(stderr, "parseInstructions(instructions=0x%0" PRIx64 ")\n",
- (uint64_t)instructionsEnd);
-
- // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
- while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
- uint64_t reg;
- uint64_t reg2;
- int64_t offset;
- uint64_t length;
- uint8_t opcode = addressSpace.get8(p);
- uint8_t operand;
-#if !defined(_LIBUNWIND_NO_HEAP)
- PrologInfoStackEntry *entry;
-#endif
- ++p;
- switch (opcode) {
- case DW_CFA_nop:
- if (logDwarf)
- fprintf(stderr, "DW_CFA_nop\n");
- break;
- case DW_CFA_set_loc:
- codeOffset =
- addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
- if (logDwarf)
- fprintf(stderr, "DW_CFA_set_loc\n");
- break;
- case DW_CFA_advance_loc1:
- codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
- p += 1;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
- break;
- case DW_CFA_advance_loc2:
- codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
- p += 2;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
- break;
- case DW_CFA_advance_loc4:
- codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
- p += 4;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
- break;
- case DW_CFA_offset_extended:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
- * cieInfo.dataAlignFactor;
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
- return false;
- }
- results->savedRegisters[reg].location = kRegisterInCFA;
- results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_offset_extended(reg=%" PRIu64 ", offset=%" PRId64 ")\n",
- reg, offset);
- break;
- case DW_CFA_restore_extended:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- ;
- if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
- return false;
- }
- results->savedRegisters[reg] = initialState.savedRegisters[reg];
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
- break;
- case DW_CFA_undefined:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
- return false;
- }
- results->savedRegisters[reg].location = kRegisterUnused;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
- break;
- case DW_CFA_same_value:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
- return false;
- }
- // <rdar://problem/8456377> DW_CFA_same_value unsupported
- // "same value" means register was stored in frame, but its current
- // value has not changed, so no need to restore from frame.
- // We model this as if the register was never saved.
- results->savedRegisters[reg].location = kRegisterUnused;
- // set flag to disable conversion to compact unwind
- results->sameValueUsed = true;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
- break;
- case DW_CFA_register:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- reg2 = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_register dwarf unwind, reg too big\n");
- return false;
- }
- if (reg2 > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
- return false;
- }
- results->savedRegisters[reg].location = kRegisterInRegister;
- results->savedRegisters[reg].value = (int64_t)reg2;
- // set flag to disable conversion to compact unwind
- results->registersInOtherRegisters = true;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n",
- reg, reg2);
- break;
-#if !defined(_LIBUNWIND_NO_HEAP)
- case DW_CFA_remember_state:
- // avoid operator new, because that would be an upward dependency
- entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
- if (entry != NULL) {
- entry->next = rememberStack;
- entry->info = *results;
- rememberStack = entry;
- } else {
- return false;
- }
- if (logDwarf)
- fprintf(stderr, "DW_CFA_remember_state\n");
- break;
- case DW_CFA_restore_state:
- if (rememberStack != NULL) {
- PrologInfoStackEntry *top = rememberStack;
- *results = top->info;
- rememberStack = top->next;
- free((char *)top);
- } else {
- return false;
- }
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore_state\n");
- break;
-#endif
- case DW_CFA_def_cfa:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
- return false;
- }
- results->cfaRegister = (uint32_t)reg;
- results->cfaRegisterOffset = (int32_t)offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n",
- reg, offset);
- break;
- case DW_CFA_def_cfa_register:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
- return false;
- }
- results->cfaRegister = (uint32_t)reg;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
- break;
- case DW_CFA_def_cfa_offset:
- results->cfaRegisterOffset = (int32_t)
- addressSpace.getULEB128(p, instructionsEnd);
- results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
- results->cfaRegisterOffset);
- break;
- case DW_CFA_def_cfa_expression:
- results->cfaRegister = 0;
- results->cfaExpression = (int64_t)p;
- length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%" PRIx64
- ", length=%" PRIu64 ")\n",
- results->cfaExpression, length);
- break;
- case DW_CFA_expression:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_expression dwarf unwind, reg too big\n");
- return false;
- }
- results->savedRegisters[reg].location = kRegisterAtExpression;
- results->savedRegisters[reg].value = (int64_t)p;
- length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_expression(reg=%" PRIu64
- ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
- reg, results->savedRegisters[reg].value, length);
- break;
- case DW_CFA_offset_extended_sf:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(
- stderr,
- "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
- return false;
- }
- offset =
- addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
- results->savedRegisters[reg].location = kRegisterInCFA;
- results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%" PRIu64
- ", offset=%" PRId64 ")\n",
- reg, offset);
- break;
- case DW_CFA_def_cfa_sf:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- offset =
- addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
- return false;
- }
- results->cfaRegister = (uint32_t)reg;
- results->cfaRegisterOffset = (int32_t)offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_def_cfa_sf(reg=%" PRIu64 ", offset=%" PRId64 ")\n", reg,
- offset);
- break;
- case DW_CFA_def_cfa_offset_sf:
- results->cfaRegisterOffset = (int32_t)
- (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
- results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
- results->cfaRegisterOffset);
- break;
- case DW_CFA_val_offset:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
- * cieInfo.dataAlignFactor;
- results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
- results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_val_offset(reg=%" PRIu64 ", offset=%" PRId64 "\n", reg,
- offset);
- break;
- case DW_CFA_val_offset_sf:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
- return false;
- }
- offset =
- addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
- results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
- results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr,
- "DW_CFA_val_offset_sf(reg=%" PRIu64 ", offset=%" PRId64 "\n",
- reg, offset);
- break;
- case DW_CFA_val_expression:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr,
- "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
- return false;
- }
- results->savedRegisters[reg].location = kRegisterIsExpression;
- results->savedRegisters[reg].value = (int64_t)p;
- length = addressSpace.getULEB128(p, instructionsEnd);
- p += length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_val_expression(reg=%" PRIu64
- ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
- reg, results->savedRegisters[reg].value, length);
- break;
- case DW_CFA_GNU_args_size:
- length = addressSpace.getULEB128(p, instructionsEnd);
- results->spExtraArgSize = (uint32_t)length;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
- break;
- case DW_CFA_GNU_negative_offset_extended:
- reg = addressSpace.getULEB128(p, instructionsEnd);
- if (reg > kMaxRegisterNumber) {
- fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf "
- "unwind, reg too big\n");
- return false;
- }
- offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
- * cieInfo.dataAlignFactor;
- results->savedRegisters[reg].location = kRegisterInCFA;
- results->savedRegisters[reg].value = -offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n",
- offset);
- break;
- default:
- operand = opcode & 0x3F;
- switch (opcode & 0xC0) {
- case DW_CFA_offset:
- reg = operand;
- offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
- * cieInfo.dataAlignFactor;
- results->savedRegisters[reg].location = kRegisterInCFA;
- results->savedRegisters[reg].value = offset;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
- operand, offset);
- break;
- case DW_CFA_advance_loc:
- codeOffset += operand * cieInfo.codeAlignFactor;
- if (logDwarf)
- fprintf(stderr, "DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
- (uint64_t)codeOffset);
- break;
- case DW_CFA_restore:
- reg = operand;
- results->savedRegisters[reg] = initialState.savedRegisters[reg];
- if (logDwarf)
- fprintf(stderr, "DW_CFA_restore(reg=%" PRIu64 ")\n", reg);
- break;
- default:
- if (logDwarf)
- fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
- return false;
- }
- }
- }
-
- return true;
-}
-
-} // namespace libunwind
-
-#endif // __DWARF_PARSER_HPP__
Index: contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/EHHeaderParser.hpp
+++ /dev/null
@@ -1,161 +0,0 @@
-//===------------------------- 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 <typename A> 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<A>::FDE_Info *fdeInfo,
- typename CFI_Parser<A>::CIE_Info *cieInfo);
-
-private:
- static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry,
- pint_t ehHdrStart, pint_t ehHdrEnd,
- uint8_t tableEnc,
- typename CFI_Parser<A>::FDE_Info *fdeInfo,
- typename CFI_Parser<A>::CIE_Info *cieInfo);
- static size_t getTableEntrySize(uint8_t tableEnc);
-};
-
-template <typename A>
-void EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
- pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
- pint_t p = ehHdrStart;
- uint8_t version = addressSpace.get8(p++);
- if (version != 1)
- _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version");
-
- 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 <typename A>
-bool EHHeaderParser<A>::decodeTableEntry(
- A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd,
- uint8_t tableEnc, typename CFI_Parser<A>::FDE_Info *fdeInfo,
- typename CFI_Parser<A>::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<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo);
- if (message != NULL) {
- _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s\n",
- message);
- return false;
- }
-
- return true;
-}
-
-template <typename A>
-bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
- uint32_t sectionLength,
- typename CFI_Parser<A>::FDE_Info *fdeInfo,
- typename CFI_Parser<A>::CIE_Info *cieInfo) {
- pint_t ehHdrEnd = ehHdrStart + sectionLength;
-
- EHHeaderParser<A>::EHHeaderInfo hdrInfo;
- EHHeaderParser<A>::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 <typename A>
-size_t EHHeaderParser<A>::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: contrib/llvm/projects/libunwind/src/Registers.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/Registers.hpp
+++ /dev/null
@@ -1,2156 +0,0 @@
-//===----------------------------- Registers.hpp --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Models register sets for supported processors.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __REGISTERS_HPP__
-#define __REGISTERS_HPP__
-
-#include <stdint.h>
-#include <string.h>
-
-#include "libunwind.h"
-#include "config.h"
-
-namespace libunwind {
-
-// For emulating 128-bit registers
-struct v128 { uint32_t vec[4]; };
-
-
-/// Registers_x86 holds the register state of a thread in a 32-bit intel
-/// process.
-class _LIBUNWIND_HIDDEN Registers_x86 {
-public:
- Registers_x86();
- Registers_x86(const void *registers);
-
- bool validRegister(int num) const;
- uint32_t getRegister(int num) const;
- void setRegister(int num, uint32_t value);
- bool validFloatRegister(int) const { return false; }
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int) const { return false; }
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 8; }
-
- uint32_t getSP() const { return _registers.__esp; }
- void setSP(uint32_t value) { _registers.__esp = value; }
- uint32_t getIP() const { return _registers.__eip; }
- void setIP(uint32_t value) { _registers.__eip = value; }
- uint32_t getEBP() const { return _registers.__ebp; }
- void setEBP(uint32_t value) { _registers.__ebp = value; }
- uint32_t getEBX() const { return _registers.__ebx; }
- void setEBX(uint32_t value) { _registers.__ebx = value; }
- uint32_t getECX() const { return _registers.__ecx; }
- void setECX(uint32_t value) { _registers.__ecx = value; }
- uint32_t getEDX() const { return _registers.__edx; }
- void setEDX(uint32_t value) { _registers.__edx = value; }
- uint32_t getESI() const { return _registers.__esi; }
- void setESI(uint32_t value) { _registers.__esi = value; }
- uint32_t getEDI() const { return _registers.__edi; }
- void setEDI(uint32_t value) { _registers.__edi = value; }
-
-private:
- struct GPRs {
- unsigned int __eax;
- unsigned int __ebx;
- unsigned int __ecx;
- unsigned int __edx;
- unsigned int __edi;
- unsigned int __esi;
- unsigned int __ebp;
- unsigned int __esp;
- unsigned int __ss;
- unsigned int __eflags;
- unsigned int __eip;
- unsigned int __cs;
- unsigned int __ds;
- unsigned int __es;
- unsigned int __fs;
- unsigned int __gs;
- };
-
- GPRs _registers;
-};
-
-inline Registers_x86::Registers_x86(const void *registers) {
- static_assert(sizeof(Registers_x86) < sizeof(unw_context_t),
- "x86 registers do not fit into unw_context_t");
- memcpy(&_registers, registers, sizeof(_registers));
-}
-
-inline Registers_x86::Registers_x86() {
- memset(&_registers, 0, sizeof(_registers));
-}
-
-inline bool Registers_x86::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum < 0)
- return false;
- if (regNum > 7)
- return false;
- return true;
-}
-
-inline uint32_t Registers_x86::getRegister(int regNum) const {
- switch (regNum) {
- case UNW_REG_IP:
- return _registers.__eip;
- case UNW_REG_SP:
- return _registers.__esp;
- case UNW_X86_EAX:
- return _registers.__eax;
- case UNW_X86_ECX:
- return _registers.__ecx;
- case UNW_X86_EDX:
- return _registers.__edx;
- case UNW_X86_EBX:
- return _registers.__ebx;
- case UNW_X86_EBP:
- return _registers.__ebp;
- case UNW_X86_ESP:
- return _registers.__esp;
- case UNW_X86_ESI:
- return _registers.__esi;
- case UNW_X86_EDI:
- return _registers.__edi;
- }
- _LIBUNWIND_ABORT("unsupported x86 register");
-}
-
-inline void Registers_x86::setRegister(int regNum, uint32_t value) {
- switch (regNum) {
- case UNW_REG_IP:
- _registers.__eip = value;
- return;
- case UNW_REG_SP:
- _registers.__esp = value;
- return;
- case UNW_X86_EAX:
- _registers.__eax = value;
- return;
- case UNW_X86_ECX:
- _registers.__ecx = value;
- return;
- case UNW_X86_EDX:
- _registers.__edx = value;
- return;
- case UNW_X86_EBX:
- _registers.__ebx = value;
- return;
- case UNW_X86_EBP:
- _registers.__ebp = value;
- return;
- case UNW_X86_ESP:
- _registers.__esp = value;
- return;
- case UNW_X86_ESI:
- _registers.__esi = value;
- return;
- case UNW_X86_EDI:
- _registers.__edi = value;
- return;
- }
- _LIBUNWIND_ABORT("unsupported x86 register");
-}
-
-inline const char *Registers_x86::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- return "ip";
- case UNW_REG_SP:
- return "esp";
- case UNW_X86_EAX:
- return "eax";
- case UNW_X86_ECX:
- return "ecx";
- case UNW_X86_EDX:
- return "edx";
- case UNW_X86_EBX:
- return "ebx";
- case UNW_X86_EBP:
- return "ebp";
- case UNW_X86_ESP:
- return "esp";
- case UNW_X86_ESI:
- return "esi";
- case UNW_X86_EDI:
- return "edi";
- default:
- return "unknown register";
- }
-}
-
-inline double Registers_x86::getFloatRegister(int) const {
- _LIBUNWIND_ABORT("no x86 float registers");
-}
-
-inline void Registers_x86::setFloatRegister(int, double) {
- _LIBUNWIND_ABORT("no x86 float registers");
-}
-
-inline v128 Registers_x86::getVectorRegister(int) const {
- _LIBUNWIND_ABORT("no x86 vector registers");
-}
-
-inline void Registers_x86::setVectorRegister(int, v128) {
- _LIBUNWIND_ABORT("no x86 vector registers");
-}
-
-
-/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
-/// process.
-class _LIBUNWIND_HIDDEN Registers_x86_64 {
-public:
- Registers_x86_64();
- Registers_x86_64(const void *registers);
-
- bool validRegister(int num) const;
- uint64_t getRegister(int num) const;
- void setRegister(int num, uint64_t value);
- bool validFloatRegister(int) const { return false; }
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int) const { return false; }
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 16; }
-
- uint64_t getSP() const { return _registers.__rsp; }
- void setSP(uint64_t value) { _registers.__rsp = value; }
- uint64_t getIP() const { return _registers.__rip; }
- void setIP(uint64_t value) { _registers.__rip = value; }
- uint64_t getRBP() const { return _registers.__rbp; }
- void setRBP(uint64_t value) { _registers.__rbp = value; }
- uint64_t getRBX() const { return _registers.__rbx; }
- void setRBX(uint64_t value) { _registers.__rbx = value; }
- uint64_t getR12() const { return _registers.__r12; }
- void setR12(uint64_t value) { _registers.__r12 = value; }
- uint64_t getR13() const { return _registers.__r13; }
- void setR13(uint64_t value) { _registers.__r13 = value; }
- uint64_t getR14() const { return _registers.__r14; }
- void setR14(uint64_t value) { _registers.__r14 = value; }
- uint64_t getR15() const { return _registers.__r15; }
- void setR15(uint64_t value) { _registers.__r15 = value; }
-
-private:
- struct GPRs {
- uint64_t __rax;
- uint64_t __rbx;
- uint64_t __rcx;
- uint64_t __rdx;
- uint64_t __rdi;
- uint64_t __rsi;
- uint64_t __rbp;
- uint64_t __rsp;
- uint64_t __r8;
- uint64_t __r9;
- uint64_t __r10;
- uint64_t __r11;
- uint64_t __r12;
- uint64_t __r13;
- uint64_t __r14;
- uint64_t __r15;
- uint64_t __rip;
- uint64_t __rflags;
- uint64_t __cs;
- uint64_t __fs;
- uint64_t __gs;
- };
- GPRs _registers;
-};
-
-inline Registers_x86_64::Registers_x86_64(const void *registers) {
- static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t),
- "x86_64 registers do not fit into unw_context_t");
- memcpy(&_registers, registers, sizeof(_registers));
-}
-
-inline Registers_x86_64::Registers_x86_64() {
- memset(&_registers, 0, sizeof(_registers));
-}
-
-inline bool Registers_x86_64::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum < 0)
- return false;
- if (regNum > 15)
- return false;
- return true;
-}
-
-inline uint64_t Registers_x86_64::getRegister(int regNum) const {
- switch (regNum) {
- case UNW_REG_IP:
- return _registers.__rip;
- case UNW_REG_SP:
- return _registers.__rsp;
- case UNW_X86_64_RAX:
- return _registers.__rax;
- case UNW_X86_64_RDX:
- return _registers.__rdx;
- case UNW_X86_64_RCX:
- return _registers.__rcx;
- case UNW_X86_64_RBX:
- return _registers.__rbx;
- case UNW_X86_64_RSI:
- return _registers.__rsi;
- case UNW_X86_64_RDI:
- return _registers.__rdi;
- case UNW_X86_64_RBP:
- return _registers.__rbp;
- case UNW_X86_64_RSP:
- return _registers.__rsp;
- case UNW_X86_64_R8:
- return _registers.__r8;
- case UNW_X86_64_R9:
- return _registers.__r9;
- case UNW_X86_64_R10:
- return _registers.__r10;
- case UNW_X86_64_R11:
- return _registers.__r11;
- case UNW_X86_64_R12:
- return _registers.__r12;
- case UNW_X86_64_R13:
- return _registers.__r13;
- case UNW_X86_64_R14:
- return _registers.__r14;
- case UNW_X86_64_R15:
- return _registers.__r15;
- }
- _LIBUNWIND_ABORT("unsupported x86_64 register");
-}
-
-inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
- switch (regNum) {
- case UNW_REG_IP:
- _registers.__rip = value;
- return;
- case UNW_REG_SP:
- _registers.__rsp = value;
- return;
- case UNW_X86_64_RAX:
- _registers.__rax = value;
- return;
- case UNW_X86_64_RDX:
- _registers.__rdx = value;
- return;
- case UNW_X86_64_RCX:
- _registers.__rcx = value;
- return;
- case UNW_X86_64_RBX:
- _registers.__rbx = value;
- return;
- case UNW_X86_64_RSI:
- _registers.__rsi = value;
- return;
- case UNW_X86_64_RDI:
- _registers.__rdi = value;
- return;
- case UNW_X86_64_RBP:
- _registers.__rbp = value;
- return;
- case UNW_X86_64_RSP:
- _registers.__rsp = value;
- return;
- case UNW_X86_64_R8:
- _registers.__r8 = value;
- return;
- case UNW_X86_64_R9:
- _registers.__r9 = value;
- return;
- case UNW_X86_64_R10:
- _registers.__r10 = value;
- return;
- case UNW_X86_64_R11:
- _registers.__r11 = value;
- return;
- case UNW_X86_64_R12:
- _registers.__r12 = value;
- return;
- case UNW_X86_64_R13:
- _registers.__r13 = value;
- return;
- case UNW_X86_64_R14:
- _registers.__r14 = value;
- return;
- case UNW_X86_64_R15:
- _registers.__r15 = value;
- return;
- }
- _LIBUNWIND_ABORT("unsupported x86_64 register");
-}
-
-inline const char *Registers_x86_64::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- return "rip";
- case UNW_REG_SP:
- return "rsp";
- case UNW_X86_64_RAX:
- return "rax";
- case UNW_X86_64_RDX:
- return "rdx";
- case UNW_X86_64_RCX:
- return "rcx";
- case UNW_X86_64_RBX:
- return "rbx";
- case UNW_X86_64_RSI:
- return "rsi";
- case UNW_X86_64_RDI:
- return "rdi";
- case UNW_X86_64_RBP:
- return "rbp";
- case UNW_X86_64_RSP:
- return "rsp";
- case UNW_X86_64_R8:
- return "r8";
- case UNW_X86_64_R9:
- return "r9";
- case UNW_X86_64_R10:
- return "r10";
- case UNW_X86_64_R11:
- return "r11";
- case UNW_X86_64_R12:
- return "r12";
- case UNW_X86_64_R13:
- return "r13";
- case UNW_X86_64_R14:
- return "r14";
- case UNW_X86_64_R15:
- return "r15";
- default:
- return "unknown register";
- }
-}
-
-inline double Registers_x86_64::getFloatRegister(int) const {
- _LIBUNWIND_ABORT("no x86_64 float registers");
-}
-
-inline void Registers_x86_64::setFloatRegister(int, double) {
- _LIBUNWIND_ABORT("no x86_64 float registers");
-}
-
-inline v128 Registers_x86_64::getVectorRegister(int) const {
- _LIBUNWIND_ABORT("no x86_64 vector registers");
-}
-
-inline void Registers_x86_64::setVectorRegister(int, v128) {
- _LIBUNWIND_ABORT("no x86_64 vector registers");
-}
-
-
-/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
-/// process.
-class _LIBUNWIND_HIDDEN Registers_ppc {
-public:
- Registers_ppc();
- Registers_ppc(const void *registers);
-
- bool validRegister(int num) const;
- uint32_t getRegister(int num) const;
- void setRegister(int num, uint32_t value);
- bool validFloatRegister(int num) const;
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int num) const;
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 112; }
-
- uint64_t getSP() const { return _registers.__r1; }
- void setSP(uint32_t value) { _registers.__r1 = value; }
- uint64_t getIP() const { return _registers.__srr0; }
- void setIP(uint32_t value) { _registers.__srr0 = value; }
-
-private:
- struct ppc_thread_state_t {
- unsigned int __srr0; /* Instruction address register (PC) */
- unsigned int __srr1; /* Machine state register (supervisor) */
- unsigned int __r0;
- unsigned int __r1;
- unsigned int __r2;
- unsigned int __r3;
- unsigned int __r4;
- unsigned int __r5;
- unsigned int __r6;
- unsigned int __r7;
- unsigned int __r8;
- unsigned int __r9;
- unsigned int __r10;
- unsigned int __r11;
- unsigned int __r12;
- unsigned int __r13;
- unsigned int __r14;
- unsigned int __r15;
- unsigned int __r16;
- unsigned int __r17;
- unsigned int __r18;
- unsigned int __r19;
- unsigned int __r20;
- unsigned int __r21;
- unsigned int __r22;
- unsigned int __r23;
- unsigned int __r24;
- unsigned int __r25;
- unsigned int __r26;
- unsigned int __r27;
- unsigned int __r28;
- unsigned int __r29;
- unsigned int __r30;
- unsigned int __r31;
- unsigned int __cr; /* Condition register */
- unsigned int __xer; /* User's integer exception register */
- unsigned int __lr; /* Link register */
- unsigned int __ctr; /* Count register */
- unsigned int __mq; /* MQ register (601 only) */
- unsigned int __vrsave; /* Vector Save Register */
- };
-
- struct ppc_float_state_t {
- double __fpregs[32];
-
- unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
- unsigned int __fpscr; /* floating point status register */
- };
-
- ppc_thread_state_t _registers;
- ppc_float_state_t _floatRegisters;
- v128 _vectorRegisters[32]; // offset 424
-};
-
-inline Registers_ppc::Registers_ppc(const void *registers) {
- static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t),
- "ppc registers do not fit into unw_context_t");
- memcpy(&_registers, static_cast<const uint8_t *>(registers),
- sizeof(_registers));
- static_assert(sizeof(ppc_thread_state_t) == 160,
- "expected float register offset to be 160");
- memcpy(&_floatRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
- sizeof(_floatRegisters));
- static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
- "expected vector register offset to be 424 bytes");
- memcpy(_vectorRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
- sizeof(ppc_float_state_t),
- sizeof(_vectorRegisters));
-}
-
-inline Registers_ppc::Registers_ppc() {
- memset(&_registers, 0, sizeof(_registers));
- memset(&_floatRegisters, 0, sizeof(_floatRegisters));
- memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
-}
-
-inline bool Registers_ppc::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum == UNW_PPC_VRSAVE)
- return true;
- if (regNum < 0)
- return false;
- if (regNum <= UNW_PPC_R31)
- return true;
- if (regNum == UNW_PPC_MQ)
- return true;
- if (regNum == UNW_PPC_LR)
- return true;
- if (regNum == UNW_PPC_CTR)
- return true;
- if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
- return true;
- return false;
-}
-
-inline uint32_t Registers_ppc::getRegister(int regNum) const {
- switch (regNum) {
- case UNW_REG_IP:
- return _registers.__srr0;
- case UNW_REG_SP:
- return _registers.__r1;
- case UNW_PPC_R0:
- return _registers.__r0;
- case UNW_PPC_R1:
- return _registers.__r1;
- case UNW_PPC_R2:
- return _registers.__r2;
- case UNW_PPC_R3:
- return _registers.__r3;
- case UNW_PPC_R4:
- return _registers.__r4;
- case UNW_PPC_R5:
- return _registers.__r5;
- case UNW_PPC_R6:
- return _registers.__r6;
- case UNW_PPC_R7:
- return _registers.__r7;
- case UNW_PPC_R8:
- return _registers.__r8;
- case UNW_PPC_R9:
- return _registers.__r9;
- case UNW_PPC_R10:
- return _registers.__r10;
- case UNW_PPC_R11:
- return _registers.__r11;
- case UNW_PPC_R12:
- return _registers.__r12;
- case UNW_PPC_R13:
- return _registers.__r13;
- case UNW_PPC_R14:
- return _registers.__r14;
- case UNW_PPC_R15:
- return _registers.__r15;
- case UNW_PPC_R16:
- return _registers.__r16;
- case UNW_PPC_R17:
- return _registers.__r17;
- case UNW_PPC_R18:
- return _registers.__r18;
- case UNW_PPC_R19:
- return _registers.__r19;
- case UNW_PPC_R20:
- return _registers.__r20;
- case UNW_PPC_R21:
- return _registers.__r21;
- case UNW_PPC_R22:
- return _registers.__r22;
- case UNW_PPC_R23:
- return _registers.__r23;
- case UNW_PPC_R24:
- return _registers.__r24;
- case UNW_PPC_R25:
- return _registers.__r25;
- case UNW_PPC_R26:
- return _registers.__r26;
- case UNW_PPC_R27:
- return _registers.__r27;
- case UNW_PPC_R28:
- return _registers.__r28;
- case UNW_PPC_R29:
- return _registers.__r29;
- case UNW_PPC_R30:
- return _registers.__r30;
- case UNW_PPC_R31:
- return _registers.__r31;
- case UNW_PPC_LR:
- return _registers.__lr;
- case UNW_PPC_CR0:
- return (_registers.__cr & 0xF0000000);
- case UNW_PPC_CR1:
- return (_registers.__cr & 0x0F000000);
- case UNW_PPC_CR2:
- return (_registers.__cr & 0x00F00000);
- case UNW_PPC_CR3:
- return (_registers.__cr & 0x000F0000);
- case UNW_PPC_CR4:
- return (_registers.__cr & 0x0000F000);
- case UNW_PPC_CR5:
- return (_registers.__cr & 0x00000F00);
- case UNW_PPC_CR6:
- return (_registers.__cr & 0x000000F0);
- case UNW_PPC_CR7:
- return (_registers.__cr & 0x0000000F);
- case UNW_PPC_VRSAVE:
- return _registers.__vrsave;
- }
- _LIBUNWIND_ABORT("unsupported ppc register");
-}
-
-inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
- //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
- switch (regNum) {
- case UNW_REG_IP:
- _registers.__srr0 = value;
- return;
- case UNW_REG_SP:
- _registers.__r1 = value;
- return;
- case UNW_PPC_R0:
- _registers.__r0 = value;
- return;
- case UNW_PPC_R1:
- _registers.__r1 = value;
- return;
- case UNW_PPC_R2:
- _registers.__r2 = value;
- return;
- case UNW_PPC_R3:
- _registers.__r3 = value;
- return;
- case UNW_PPC_R4:
- _registers.__r4 = value;
- return;
- case UNW_PPC_R5:
- _registers.__r5 = value;
- return;
- case UNW_PPC_R6:
- _registers.__r6 = value;
- return;
- case UNW_PPC_R7:
- _registers.__r7 = value;
- return;
- case UNW_PPC_R8:
- _registers.__r8 = value;
- return;
- case UNW_PPC_R9:
- _registers.__r9 = value;
- return;
- case UNW_PPC_R10:
- _registers.__r10 = value;
- return;
- case UNW_PPC_R11:
- _registers.__r11 = value;
- return;
- case UNW_PPC_R12:
- _registers.__r12 = value;
- return;
- case UNW_PPC_R13:
- _registers.__r13 = value;
- return;
- case UNW_PPC_R14:
- _registers.__r14 = value;
- return;
- case UNW_PPC_R15:
- _registers.__r15 = value;
- return;
- case UNW_PPC_R16:
- _registers.__r16 = value;
- return;
- case UNW_PPC_R17:
- _registers.__r17 = value;
- return;
- case UNW_PPC_R18:
- _registers.__r18 = value;
- return;
- case UNW_PPC_R19:
- _registers.__r19 = value;
- return;
- case UNW_PPC_R20:
- _registers.__r20 = value;
- return;
- case UNW_PPC_R21:
- _registers.__r21 = value;
- return;
- case UNW_PPC_R22:
- _registers.__r22 = value;
- return;
- case UNW_PPC_R23:
- _registers.__r23 = value;
- return;
- case UNW_PPC_R24:
- _registers.__r24 = value;
- return;
- case UNW_PPC_R25:
- _registers.__r25 = value;
- return;
- case UNW_PPC_R26:
- _registers.__r26 = value;
- return;
- case UNW_PPC_R27:
- _registers.__r27 = value;
- return;
- case UNW_PPC_R28:
- _registers.__r28 = value;
- return;
- case UNW_PPC_R29:
- _registers.__r29 = value;
- return;
- case UNW_PPC_R30:
- _registers.__r30 = value;
- return;
- case UNW_PPC_R31:
- _registers.__r31 = value;
- return;
- case UNW_PPC_MQ:
- _registers.__mq = value;
- return;
- case UNW_PPC_LR:
- _registers.__lr = value;
- return;
- case UNW_PPC_CTR:
- _registers.__ctr = value;
- return;
- case UNW_PPC_CR0:
- _registers.__cr &= 0x0FFFFFFF;
- _registers.__cr |= (value & 0xF0000000);
- return;
- case UNW_PPC_CR1:
- _registers.__cr &= 0xF0FFFFFF;
- _registers.__cr |= (value & 0x0F000000);
- return;
- case UNW_PPC_CR2:
- _registers.__cr &= 0xFF0FFFFF;
- _registers.__cr |= (value & 0x00F00000);
- return;
- case UNW_PPC_CR3:
- _registers.__cr &= 0xFFF0FFFF;
- _registers.__cr |= (value & 0x000F0000);
- return;
- case UNW_PPC_CR4:
- _registers.__cr &= 0xFFFF0FFF;
- _registers.__cr |= (value & 0x0000F000);
- return;
- case UNW_PPC_CR5:
- _registers.__cr &= 0xFFFFF0FF;
- _registers.__cr |= (value & 0x00000F00);
- return;
- case UNW_PPC_CR6:
- _registers.__cr &= 0xFFFFFF0F;
- _registers.__cr |= (value & 0x000000F0);
- return;
- case UNW_PPC_CR7:
- _registers.__cr &= 0xFFFFFFF0;
- _registers.__cr |= (value & 0x0000000F);
- return;
- case UNW_PPC_VRSAVE:
- _registers.__vrsave = value;
- return;
- // not saved
- return;
- case UNW_PPC_XER:
- _registers.__xer = value;
- return;
- case UNW_PPC_AP:
- case UNW_PPC_VSCR:
- case UNW_PPC_SPEFSCR:
- // not saved
- return;
- }
- _LIBUNWIND_ABORT("unsupported ppc register");
-}
-
-inline bool Registers_ppc::validFloatRegister(int regNum) const {
- if (regNum < UNW_PPC_F0)
- return false;
- if (regNum > UNW_PPC_F31)
- return false;
- return true;
-}
-
-inline double Registers_ppc::getFloatRegister(int regNum) const {
- assert(validFloatRegister(regNum));
- return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
-}
-
-inline void Registers_ppc::setFloatRegister(int regNum, double value) {
- assert(validFloatRegister(regNum));
- _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
-}
-
-inline bool Registers_ppc::validVectorRegister(int regNum) const {
- if (regNum < UNW_PPC_V0)
- return false;
- if (regNum > UNW_PPC_V31)
- return false;
- return true;
-}
-
-inline v128 Registers_ppc::getVectorRegister(int regNum) const {
- assert(validVectorRegister(regNum));
- v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
- return result;
-}
-
-inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
- assert(validVectorRegister(regNum));
- _vectorRegisters[regNum - UNW_PPC_V0] = value;
-}
-
-inline const char *Registers_ppc::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- return "ip";
- case UNW_REG_SP:
- return "sp";
- case UNW_PPC_R0:
- return "r0";
- case UNW_PPC_R1:
- return "r1";
- case UNW_PPC_R2:
- return "r2";
- case UNW_PPC_R3:
- return "r3";
- case UNW_PPC_R4:
- return "r4";
- case UNW_PPC_R5:
- return "r5";
- case UNW_PPC_R6:
- return "r6";
- case UNW_PPC_R7:
- return "r7";
- case UNW_PPC_R8:
- return "r8";
- case UNW_PPC_R9:
- return "r9";
- case UNW_PPC_R10:
- return "r10";
- case UNW_PPC_R11:
- return "r11";
- case UNW_PPC_R12:
- return "r12";
- case UNW_PPC_R13:
- return "r13";
- case UNW_PPC_R14:
- return "r14";
- case UNW_PPC_R15:
- return "r15";
- case UNW_PPC_R16:
- return "r16";
- case UNW_PPC_R17:
- return "r17";
- case UNW_PPC_R18:
- return "r18";
- case UNW_PPC_R19:
- return "r19";
- case UNW_PPC_R20:
- return "r20";
- case UNW_PPC_R21:
- return "r21";
- case UNW_PPC_R22:
- return "r22";
- case UNW_PPC_R23:
- return "r23";
- case UNW_PPC_R24:
- return "r24";
- case UNW_PPC_R25:
- return "r25";
- case UNW_PPC_R26:
- return "r26";
- case UNW_PPC_R27:
- return "r27";
- case UNW_PPC_R28:
- return "r28";
- case UNW_PPC_R29:
- return "r29";
- case UNW_PPC_R30:
- return "r30";
- case UNW_PPC_R31:
- return "r31";
- case UNW_PPC_F0:
- return "fp0";
- case UNW_PPC_F1:
- return "fp1";
- case UNW_PPC_F2:
- return "fp2";
- case UNW_PPC_F3:
- return "fp3";
- case UNW_PPC_F4:
- return "fp4";
- case UNW_PPC_F5:
- return "fp5";
- case UNW_PPC_F6:
- return "fp6";
- case UNW_PPC_F7:
- return "fp7";
- case UNW_PPC_F8:
- return "fp8";
- case UNW_PPC_F9:
- return "fp9";
- case UNW_PPC_F10:
- return "fp10";
- case UNW_PPC_F11:
- return "fp11";
- case UNW_PPC_F12:
- return "fp12";
- case UNW_PPC_F13:
- return "fp13";
- case UNW_PPC_F14:
- return "fp14";
- case UNW_PPC_F15:
- return "fp15";
- case UNW_PPC_F16:
- return "fp16";
- case UNW_PPC_F17:
- return "fp17";
- case UNW_PPC_F18:
- return "fp18";
- case UNW_PPC_F19:
- return "fp19";
- case UNW_PPC_F20:
- return "fp20";
- case UNW_PPC_F21:
- return "fp21";
- case UNW_PPC_F22:
- return "fp22";
- case UNW_PPC_F23:
- return "fp23";
- case UNW_PPC_F24:
- return "fp24";
- case UNW_PPC_F25:
- return "fp25";
- case UNW_PPC_F26:
- return "fp26";
- case UNW_PPC_F27:
- return "fp27";
- case UNW_PPC_F28:
- return "fp28";
- case UNW_PPC_F29:
- return "fp29";
- case UNW_PPC_F30:
- return "fp30";
- case UNW_PPC_F31:
- return "fp31";
- case UNW_PPC_LR:
- return "lr";
- default:
- return "unknown register";
- }
-
-}
-
-/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V
-/// process.
-class _LIBUNWIND_HIDDEN Registers_riscv {
-public:
- Registers_riscv();
- Registers_riscv(const void *registers);
-
- bool validRegister(int num) const;
- uint64_t getRegister(int num) const;
- void setRegister(int num, uint64_t value);
- bool validFloatRegister(int num) const;
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int num) const;
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 95; }
-
- uint64_t getSP() const { return _registers.__x[2]; }
- void setSP(uint64_t value) { _registers.__x[2] = value; }
- uint64_t getIP() const { return _registers.__x[1]; }
- void setIP(uint64_t value) { _registers.__x[1] = value; }
-
-private:
- struct GPRs {
- uint64_t __x[32]; // x0-x31
- };
-
- GPRs _registers;
- double _vectorHalfRegisters[32];
- // Currently only the lower double in 128-bit vectore registers
- // is perserved during unwinding. We could define new register
- // numbers (> 96) which mean whole vector registers, then this
- // struct would need to change to contain whole vector registers.
-};
-
-inline Registers_riscv::Registers_riscv(const void *registers) {
- static_assert(sizeof(Registers_riscv) < sizeof(unw_context_t),
- "riscv registers do not fit into unw_context_t");
- memcpy(&_registers, registers, sizeof(_registers));
- static_assert(sizeof(GPRs) == 0x100,
- "expected VFP registers to be at offset 256");
- memcpy(_vectorHalfRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(GPRs),
- sizeof(_vectorHalfRegisters));
-}
-
-inline Registers_riscv::Registers_riscv() {
- memset(&_registers, 0, sizeof(_registers));
- memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
-}
-
-inline bool Registers_riscv::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum < 0)
- return false;
- if (regNum > 95)
- return false;
- if ((regNum > 31) && (regNum < 64))
- return false;
- return true;
-}
-
-inline uint64_t Registers_riscv::getRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return _registers.__x[1];
- if (regNum == UNW_REG_SP)
- return _registers.__x[2];
- if ((regNum >= 0) && (regNum < 32))
- return _registers.__x[regNum];
- _LIBUNWIND_ABORT("unsupported riscv register");
-}
-
-inline void Registers_riscv::setRegister(int regNum, uint64_t value) {
- if (regNum == UNW_REG_IP)
- _registers.__x[1] = value;
- else if (regNum == UNW_REG_SP)
- _registers.__x[2] = value;
- else if ((regNum >= 0) && (regNum < 32))
- _registers.__x[regNum] = value;
- else
- _LIBUNWIND_ABORT("unsupported riscv register");
-}
-
-inline const char *Registers_riscv::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- return "ra";
- case UNW_REG_SP:
- return "sp";
- case UNW_RISCV_X0:
- return "x0";
- case UNW_RISCV_X1:
- return "ra";
- case UNW_RISCV_X2:
- return "sp";
- case UNW_RISCV_X3:
- return "x3";
- case UNW_RISCV_X4:
- return "x4";
- case UNW_RISCV_X5:
- return "x5";
- case UNW_RISCV_X6:
- return "x6";
- case UNW_RISCV_X7:
- return "x7";
- case UNW_RISCV_X8:
- return "x8";
- case UNW_RISCV_X9:
- return "x9";
- case UNW_RISCV_X10:
- return "x10";
- case UNW_RISCV_X11:
- return "x11";
- case UNW_RISCV_X12:
- return "x12";
- case UNW_RISCV_X13:
- return "x13";
- case UNW_RISCV_X14:
- return "x14";
- case UNW_RISCV_X15:
- return "x15";
- case UNW_RISCV_X16:
- return "x16";
- case UNW_RISCV_X17:
- return "x17";
- case UNW_RISCV_X18:
- return "x18";
- case UNW_RISCV_X19:
- return "x19";
- case UNW_RISCV_X20:
- return "x20";
- case UNW_RISCV_X21:
- return "x21";
- case UNW_RISCV_X22:
- return "x22";
- case UNW_RISCV_X23:
- return "x23";
- case UNW_RISCV_X24:
- return "x24";
- case UNW_RISCV_X25:
- return "x25";
- case UNW_RISCV_X26:
- return "x26";
- case UNW_RISCV_X27:
- return "x27";
- case UNW_RISCV_X28:
- return "x28";
- case UNW_RISCV_X29:
- return "x29";
- case UNW_RISCV_X30:
- return "x30";
- case UNW_RISCV_X31:
- return "x31";
- case UNW_RISCV_D0:
- return "d0";
- case UNW_RISCV_D1:
- return "d1";
- case UNW_RISCV_D2:
- return "d2";
- case UNW_RISCV_D3:
- return "d3";
- case UNW_RISCV_D4:
- return "d4";
- case UNW_RISCV_D5:
- return "d5";
- case UNW_RISCV_D6:
- return "d6";
- case UNW_RISCV_D7:
- return "d7";
- case UNW_RISCV_D8:
- return "d8";
- case UNW_RISCV_D9:
- return "d9";
- case UNW_RISCV_D10:
- return "d10";
- case UNW_RISCV_D11:
- return "d11";
- case UNW_RISCV_D12:
- return "d12";
- case UNW_RISCV_D13:
- return "d13";
- case UNW_RISCV_D14:
- return "d14";
- case UNW_RISCV_D15:
- return "d15";
- case UNW_RISCV_D16:
- return "d16";
- case UNW_RISCV_D17:
- return "d17";
- case UNW_RISCV_D18:
- return "d18";
- case UNW_RISCV_D19:
- return "d19";
- case UNW_RISCV_D20:
- return "d20";
- case UNW_RISCV_D21:
- return "d21";
- case UNW_RISCV_D22:
- return "d22";
- case UNW_RISCV_D23:
- return "d23";
- case UNW_RISCV_D24:
- return "d24";
- case UNW_RISCV_D25:
- return "d25";
- case UNW_RISCV_D26:
- return "d26";
- case UNW_RISCV_D27:
- return "d27";
- case UNW_RISCV_D28:
- return "d28";
- case UNW_RISCV_D29:
- return "d29";
- case UNW_RISCV_D30:
- return "d30";
- case UNW_RISCV_D31:
- return "d31";
- default:
- return "unknown register";
- }
-}
-
-inline bool Registers_riscv::validFloatRegister(int regNum) const {
- if (regNum < UNW_RISCV_D0)
- return false;
- if (regNum > UNW_RISCV_D31)
- return false;
- return true;
-}
-
-inline double Registers_riscv::getFloatRegister(int regNum) const {
- assert(validFloatRegister(regNum));
- return _vectorHalfRegisters[regNum - UNW_RISCV_D0];
-}
-
-inline void Registers_riscv::setFloatRegister(int regNum, double value) {
- assert(validFloatRegister(regNum));
- _vectorHalfRegisters[regNum - UNW_RISCV_D0] = value;
-}
-
-inline bool Registers_riscv::validVectorRegister(int) const {
- return false;
-}
-
-inline v128 Registers_riscv::getVectorRegister(int) const {
- _LIBUNWIND_ABORT("no riscv vector register support yet");
-}
-
-inline void Registers_riscv::setVectorRegister(int, v128) {
- _LIBUNWIND_ABORT("no riscv vector register support yet");
-}
-
-
-/// Registers_arm64 holds the register state of a thread in a 64-bit arm
-/// process.
-class _LIBUNWIND_HIDDEN Registers_arm64 {
-public:
- Registers_arm64();
- Registers_arm64(const void *registers);
-
- bool validRegister(int num) const;
- uint64_t getRegister(int num) const;
- void setRegister(int num, uint64_t value);
- bool validFloatRegister(int num) const;
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int num) const;
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 95; }
-
- uint64_t getSP() const { return _registers.__sp; }
- void setSP(uint64_t value) { _registers.__sp = value; }
- uint64_t getIP() const { return _registers.__pc; }
- void setIP(uint64_t value) { _registers.__pc = value; }
- uint64_t getFP() const { return _registers.__fp; }
- void setFP(uint64_t value) { _registers.__fp = value; }
-
-private:
- struct GPRs {
- uint64_t __x[29]; // x0-x28
- uint64_t __fp; // Frame pointer x29
- uint64_t __lr; // Link register x30
- uint64_t __sp; // Stack pointer x31
- uint64_t __pc; // Program counter
- uint64_t padding; // 16-byte align
- };
-
- GPRs _registers;
- double _vectorHalfRegisters[32];
- // Currently only the lower double in 128-bit vectore registers
- // is perserved during unwinding. We could define new register
- // numbers (> 96) which mean whole vector registers, then this
- // struct would need to change to contain whole vector registers.
-};
-
-inline Registers_arm64::Registers_arm64(const void *registers) {
- static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t),
- "arm64 registers do not fit into unw_context_t");
- memcpy(&_registers, registers, sizeof(_registers));
- static_assert(sizeof(GPRs) == 0x110,
- "expected VFP registers to be at offset 272");
- memcpy(_vectorHalfRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(GPRs),
- sizeof(_vectorHalfRegisters));
-}
-
-inline Registers_arm64::Registers_arm64() {
- memset(&_registers, 0, sizeof(_registers));
- memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
-}
-
-inline bool Registers_arm64::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum < 0)
- return false;
- if (regNum > 95)
- return false;
- if ((regNum > 31) && (regNum < 64))
- return false;
- return true;
-}
-
-inline uint64_t Registers_arm64::getRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return _registers.__pc;
- if (regNum == UNW_REG_SP)
- return _registers.__sp;
- if ((regNum >= 0) && (regNum < 32))
- return _registers.__x[regNum];
- _LIBUNWIND_ABORT("unsupported arm64 register");
-}
-
-inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
- if (regNum == UNW_REG_IP)
- _registers.__pc = value;
- else if (regNum == UNW_REG_SP)
- _registers.__sp = value;
- else if ((regNum >= 0) && (regNum < 32))
- _registers.__x[regNum] = value;
- else
- _LIBUNWIND_ABORT("unsupported arm64 register");
-}
-
-inline const char *Registers_arm64::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- return "pc";
- case UNW_REG_SP:
- return "sp";
- case UNW_ARM64_X0:
- return "x0";
- case UNW_ARM64_X1:
- return "x1";
- case UNW_ARM64_X2:
- return "x2";
- case UNW_ARM64_X3:
- return "x3";
- case UNW_ARM64_X4:
- return "x4";
- case UNW_ARM64_X5:
- return "x5";
- case UNW_ARM64_X6:
- return "x6";
- case UNW_ARM64_X7:
- return "x7";
- case UNW_ARM64_X8:
- return "x8";
- case UNW_ARM64_X9:
- return "x9";
- case UNW_ARM64_X10:
- return "x10";
- case UNW_ARM64_X11:
- return "x11";
- case UNW_ARM64_X12:
- return "x12";
- case UNW_ARM64_X13:
- return "x13";
- case UNW_ARM64_X14:
- return "x14";
- case UNW_ARM64_X15:
- return "x15";
- case UNW_ARM64_X16:
- return "x16";
- case UNW_ARM64_X17:
- return "x17";
- case UNW_ARM64_X18:
- return "x18";
- case UNW_ARM64_X19:
- return "x19";
- case UNW_ARM64_X20:
- return "x20";
- case UNW_ARM64_X21:
- return "x21";
- case UNW_ARM64_X22:
- return "x22";
- case UNW_ARM64_X23:
- return "x23";
- case UNW_ARM64_X24:
- return "x24";
- case UNW_ARM64_X25:
- return "x25";
- case UNW_ARM64_X26:
- return "x26";
- case UNW_ARM64_X27:
- return "x27";
- case UNW_ARM64_X28:
- return "x28";
- case UNW_ARM64_X29:
- return "fp";
- case UNW_ARM64_X30:
- return "lr";
- case UNW_ARM64_X31:
- return "sp";
- case UNW_ARM64_D0:
- return "d0";
- case UNW_ARM64_D1:
- return "d1";
- case UNW_ARM64_D2:
- return "d2";
- case UNW_ARM64_D3:
- return "d3";
- case UNW_ARM64_D4:
- return "d4";
- case UNW_ARM64_D5:
- return "d5";
- case UNW_ARM64_D6:
- return "d6";
- case UNW_ARM64_D7:
- return "d7";
- case UNW_ARM64_D8:
- return "d8";
- case UNW_ARM64_D9:
- return "d9";
- case UNW_ARM64_D10:
- return "d10";
- case UNW_ARM64_D11:
- return "d11";
- case UNW_ARM64_D12:
- return "d12";
- case UNW_ARM64_D13:
- return "d13";
- case UNW_ARM64_D14:
- return "d14";
- case UNW_ARM64_D15:
- return "d15";
- case UNW_ARM64_D16:
- return "d16";
- case UNW_ARM64_D17:
- return "d17";
- case UNW_ARM64_D18:
- return "d18";
- case UNW_ARM64_D19:
- return "d19";
- case UNW_ARM64_D20:
- return "d20";
- case UNW_ARM64_D21:
- return "d21";
- case UNW_ARM64_D22:
- return "d22";
- case UNW_ARM64_D23:
- return "d23";
- case UNW_ARM64_D24:
- return "d24";
- case UNW_ARM64_D25:
- return "d25";
- case UNW_ARM64_D26:
- return "d26";
- case UNW_ARM64_D27:
- return "d27";
- case UNW_ARM64_D28:
- return "d28";
- case UNW_ARM64_D29:
- return "d29";
- case UNW_ARM64_D30:
- return "d30";
- case UNW_ARM64_D31:
- return "d31";
- default:
- return "unknown register";
- }
-}
-
-inline bool Registers_arm64::validFloatRegister(int regNum) const {
- if (regNum < UNW_ARM64_D0)
- return false;
- if (regNum > UNW_ARM64_D31)
- return false;
- return true;
-}
-
-inline double Registers_arm64::getFloatRegister(int regNum) const {
- assert(validFloatRegister(regNum));
- return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
-}
-
-inline void Registers_arm64::setFloatRegister(int regNum, double value) {
- assert(validFloatRegister(regNum));
- _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
-}
-
-inline bool Registers_arm64::validVectorRegister(int) const {
- return false;
-}
-
-inline v128 Registers_arm64::getVectorRegister(int) const {
- _LIBUNWIND_ABORT("no arm64 vector register support yet");
-}
-
-inline void Registers_arm64::setVectorRegister(int, v128) {
- _LIBUNWIND_ABORT("no arm64 vector register support yet");
-}
-
-/// Registers_arm holds the register state of a thread in a 32-bit arm
-/// process.
-///
-/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
-/// this uses more memory than required.
-class _LIBUNWIND_HIDDEN Registers_arm {
-public:
- Registers_arm();
- Registers_arm(const void *registers);
-
- bool validRegister(int num) const;
- uint32_t getRegister(int num);
- void setRegister(int num, uint32_t value);
- bool validFloatRegister(int num) const;
- unw_fpreg_t getFloatRegister(int num);
- void setFloatRegister(int num, unw_fpreg_t value);
- bool validVectorRegister(int num) const;
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto() {
- restoreSavedFloatRegisters();
- restoreCoreAndJumpTo();
- }
-
- uint32_t getSP() const { return _registers.__sp; }
- void setSP(uint32_t value) { _registers.__sp = value; }
- uint32_t getIP() const { return _registers.__pc; }
- void setIP(uint32_t value) { _registers.__pc = value; }
-
- void saveVFPAsX() {
- assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
- _use_X_for_vfp_save = true;
- }
-
- void restoreSavedFloatRegisters() {
- if (_saved_vfp_d0_d15) {
- if (_use_X_for_vfp_save)
- restoreVFPWithFLDMX(_vfp_d0_d15_pad);
- else
- restoreVFPWithFLDMD(_vfp_d0_d15_pad);
- }
- if (_saved_vfp_d16_d31)
- restoreVFPv3(_vfp_d16_d31);
- if (_saved_iwmmx)
- restoreiWMMX(_iwmmx);
- if (_saved_iwmmx_control)
- restoreiWMMXControl(_iwmmx_control);
- }
-
-private:
- struct GPRs {
- uint32_t __r[13]; // r0-r12
- uint32_t __sp; // Stack pointer r13
- uint32_t __lr; // Link register r14
- uint32_t __pc; // Program counter r15
- };
-
- static void saveVFPWithFSTMD(unw_fpreg_t*);
- static void saveVFPWithFSTMX(unw_fpreg_t*);
- static void saveVFPv3(unw_fpreg_t*);
- static void saveiWMMX(unw_fpreg_t*);
- static void saveiWMMXControl(uint32_t*);
- static void restoreVFPWithFLDMD(unw_fpreg_t*);
- static void restoreVFPWithFLDMX(unw_fpreg_t*);
- static void restoreVFPv3(unw_fpreg_t*);
- static void restoreiWMMX(unw_fpreg_t*);
- static void restoreiWMMXControl(uint32_t*);
- void restoreCoreAndJumpTo();
-
- // ARM registers
- GPRs _registers;
-
- // We save floating point registers lazily because we can't know ahead of
- // time which ones are used. See EHABI #4.7.
-
- // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
- //
- // See EHABI #7.5 that explains how matching instruction sequences for load
- // and store need to be used to correctly restore the exact register bits.
- bool _use_X_for_vfp_save;
- // Whether VFP D0-D15 are saved.
- bool _saved_vfp_d0_d15;
- // Whether VFPv3 D16-D31 are saved.
- bool _saved_vfp_d16_d31;
- // Whether iWMMX data registers are saved.
- bool _saved_iwmmx;
- // Whether iWMMX control registers are saved.
- bool _saved_iwmmx_control;
- // VFP registers D0-D15, + padding if saved using FSTMX
- unw_fpreg_t _vfp_d0_d15_pad[17];
- // VFPv3 registers D16-D31, always saved using FSTMD
- unw_fpreg_t _vfp_d16_d31[16];
- // iWMMX registers
- unw_fpreg_t _iwmmx[16];
- // iWMMX control registers
- uint32_t _iwmmx_control[4];
-};
-
-inline Registers_arm::Registers_arm(const void *registers)
- : _use_X_for_vfp_save(false),
- _saved_vfp_d0_d15(false),
- _saved_vfp_d16_d31(false),
- _saved_iwmmx(false),
- _saved_iwmmx_control(false) {
- static_assert(sizeof(Registers_arm) < sizeof(unw_context_t),
- "arm registers do not fit into unw_context_t");
- // See unw_getcontext() note about data.
- memcpy(&_registers, registers, sizeof(_registers));
- memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
- memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
- memset(&_iwmmx, 0, sizeof(_iwmmx));
- memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
-}
-
-inline Registers_arm::Registers_arm()
- : _use_X_for_vfp_save(false),
- _saved_vfp_d0_d15(false),
- _saved_vfp_d16_d31(false),
- _saved_iwmmx(false),
- _saved_iwmmx_control(false) {
- memset(&_registers, 0, sizeof(_registers));
- memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
- memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
- memset(&_iwmmx, 0, sizeof(_iwmmx));
- memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
-}
-
-inline bool Registers_arm::validRegister(int regNum) const {
- // Returns true for all non-VFP registers supported by the EHABI
- // virtual register set (VRS).
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
- return true;
- if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
- return true;
- return false;
-}
-
-inline uint32_t Registers_arm::getRegister(int regNum) {
- if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
- return _registers.__sp;
- if (regNum == UNW_ARM_LR)
- return _registers.__lr;
- if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
- return _registers.__pc;
- if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
- return _registers.__r[regNum];
- if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
- if (!_saved_iwmmx_control) {
- _saved_iwmmx_control = true;
- saveiWMMXControl(_iwmmx_control);
- }
- return _iwmmx_control[regNum - UNW_ARM_WC0];
- }
- _LIBUNWIND_ABORT("unsupported arm register");
-}
-
-inline void Registers_arm::setRegister(int regNum, uint32_t value) {
- if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
- _registers.__sp = value;
- else if (regNum == UNW_ARM_LR)
- _registers.__lr = value;
- else if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
- _registers.__pc = value;
- else if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
- _registers.__r[regNum] = value;
- else if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
- if (!_saved_iwmmx_control) {
- _saved_iwmmx_control = true;
- saveiWMMXControl(_iwmmx_control);
- }
- _iwmmx_control[regNum - UNW_ARM_WC0] = value;
- } else
- _LIBUNWIND_ABORT("unsupported arm register");
-}
-
-inline const char *Registers_arm::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_REG_IP:
- case UNW_ARM_IP: // UNW_ARM_R15 is alias
- return "pc";
- case UNW_ARM_LR: // UNW_ARM_R14 is alias
- return "lr";
- case UNW_REG_SP:
- case UNW_ARM_SP: // UNW_ARM_R13 is alias
- return "sp";
- case UNW_ARM_R0:
- return "r0";
- case UNW_ARM_R1:
- return "r1";
- case UNW_ARM_R2:
- return "r2";
- case UNW_ARM_R3:
- return "r3";
- case UNW_ARM_R4:
- return "r4";
- case UNW_ARM_R5:
- return "r5";
- case UNW_ARM_R6:
- return "r6";
- case UNW_ARM_R7:
- return "r7";
- case UNW_ARM_R8:
- return "r8";
- case UNW_ARM_R9:
- return "r9";
- case UNW_ARM_R10:
- return "r10";
- case UNW_ARM_R11:
- return "r11";
- case UNW_ARM_R12:
- return "r12";
- case UNW_ARM_S0:
- return "s0";
- case UNW_ARM_S1:
- return "s1";
- case UNW_ARM_S2:
- return "s2";
- case UNW_ARM_S3:
- return "s3";
- case UNW_ARM_S4:
- return "s4";
- case UNW_ARM_S5:
- return "s5";
- case UNW_ARM_S6:
- return "s6";
- case UNW_ARM_S7:
- return "s7";
- case UNW_ARM_S8:
- return "s8";
- case UNW_ARM_S9:
- return "s9";
- case UNW_ARM_S10:
- return "s10";
- case UNW_ARM_S11:
- return "s11";
- case UNW_ARM_S12:
- return "s12";
- case UNW_ARM_S13:
- return "s13";
- case UNW_ARM_S14:
- return "s14";
- case UNW_ARM_S15:
- return "s15";
- case UNW_ARM_S16:
- return "s16";
- case UNW_ARM_S17:
- return "s17";
- case UNW_ARM_S18:
- return "s18";
- case UNW_ARM_S19:
- return "s19";
- case UNW_ARM_S20:
- return "s20";
- case UNW_ARM_S21:
- return "s21";
- case UNW_ARM_S22:
- return "s22";
- case UNW_ARM_S23:
- return "s23";
- case UNW_ARM_S24:
- return "s24";
- case UNW_ARM_S25:
- return "s25";
- case UNW_ARM_S26:
- return "s26";
- case UNW_ARM_S27:
- return "s27";
- case UNW_ARM_S28:
- return "s28";
- case UNW_ARM_S29:
- return "s29";
- case UNW_ARM_S30:
- return "s30";
- case UNW_ARM_S31:
- return "s31";
- case UNW_ARM_D0:
- return "d0";
- case UNW_ARM_D1:
- return "d1";
- case UNW_ARM_D2:
- return "d2";
- case UNW_ARM_D3:
- return "d3";
- case UNW_ARM_D4:
- return "d4";
- case UNW_ARM_D5:
- return "d5";
- case UNW_ARM_D6:
- return "d6";
- case UNW_ARM_D7:
- return "d7";
- case UNW_ARM_D8:
- return "d8";
- case UNW_ARM_D9:
- return "d9";
- case UNW_ARM_D10:
- return "d10";
- case UNW_ARM_D11:
- return "d11";
- case UNW_ARM_D12:
- return "d12";
- case UNW_ARM_D13:
- return "d13";
- case UNW_ARM_D14:
- return "d14";
- case UNW_ARM_D15:
- return "d15";
- case UNW_ARM_D16:
- return "d16";
- case UNW_ARM_D17:
- return "d17";
- case UNW_ARM_D18:
- return "d18";
- case UNW_ARM_D19:
- return "d19";
- case UNW_ARM_D20:
- return "d20";
- case UNW_ARM_D21:
- return "d21";
- case UNW_ARM_D22:
- return "d22";
- case UNW_ARM_D23:
- return "d23";
- case UNW_ARM_D24:
- return "d24";
- case UNW_ARM_D25:
- return "d25";
- case UNW_ARM_D26:
- return "d26";
- case UNW_ARM_D27:
- return "d27";
- case UNW_ARM_D28:
- return "d28";
- case UNW_ARM_D29:
- return "d29";
- case UNW_ARM_D30:
- return "d30";
- case UNW_ARM_D31:
- return "d31";
- default:
- return "unknown register";
- }
-}
-
-inline bool Registers_arm::validFloatRegister(int regNum) const {
- // NOTE: Consider the intel MMX registers floating points so the
- // unw_get_fpreg can be used to transmit the 64-bit data back.
- return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
- || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15));
-}
-
-inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
- if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
- if (!_saved_vfp_d0_d15) {
- _saved_vfp_d0_d15 = true;
- if (_use_X_for_vfp_save)
- saveVFPWithFSTMX(_vfp_d0_d15_pad);
- else
- saveVFPWithFSTMD(_vfp_d0_d15_pad);
- }
- return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
- } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
- if (!_saved_vfp_d16_d31) {
- _saved_vfp_d16_d31 = true;
- saveVFPv3(_vfp_d16_d31);
- }
- return _vfp_d16_d31[regNum - UNW_ARM_D16];
- } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
- if (!_saved_iwmmx) {
- _saved_iwmmx = true;
- saveiWMMX(_iwmmx);
- }
- return _iwmmx[regNum - UNW_ARM_WR0];
- } else {
- _LIBUNWIND_ABORT("Unknown ARM float register");
- }
-}
-
-inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
- if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
- if (!_saved_vfp_d0_d15) {
- _saved_vfp_d0_d15 = true;
- if (_use_X_for_vfp_save)
- saveVFPWithFSTMX(_vfp_d0_d15_pad);
- else
- saveVFPWithFSTMD(_vfp_d0_d15_pad);
- }
- _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
- } else if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
- if (!_saved_vfp_d16_d31) {
- _saved_vfp_d16_d31 = true;
- saveVFPv3(_vfp_d16_d31);
- }
- _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
- } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
- if (!_saved_iwmmx) {
- _saved_iwmmx = true;
- saveiWMMX(_iwmmx);
- }
- _iwmmx[regNum - UNW_ARM_WR0] = value;
- } else {
- _LIBUNWIND_ABORT("Unknown ARM float register");
- }
-}
-
-inline bool Registers_arm::validVectorRegister(int) const {
- return false;
-}
-
-inline v128 Registers_arm::getVectorRegister(int) const {
- _LIBUNWIND_ABORT("ARM vector support not implemented");
-}
-
-inline void Registers_arm::setVectorRegister(int, v128) {
- _LIBUNWIND_ABORT("ARM vector support not implemented");
-}
-/// Registers_or1k holds the register state of a thread in an OpenRISC1000
-/// process.
-class _LIBUNWIND_HIDDEN Registers_or1k {
-public:
- Registers_or1k();
- Registers_or1k(const void *registers);
-
- bool validRegister(int num) const;
- uint32_t getRegister(int num) const;
- void setRegister(int num, uint32_t value);
- bool validFloatRegister(int num) const;
- double getFloatRegister(int num) const;
- void setFloatRegister(int num, double value);
- bool validVectorRegister(int num) const;
- v128 getVectorRegister(int num) const;
- void setVectorRegister(int num, v128 value);
- const char *getRegisterName(int num);
- void jumpto();
- static int lastDwarfRegNum() { return 31; }
-
- uint64_t getSP() const { return _registers.__r[1]; }
- void setSP(uint32_t value) { _registers.__r[1] = value; }
- uint64_t getIP() const { return _registers.__r[9]; }
- void setIP(uint32_t value) { _registers.__r[9] = value; }
-
-private:
- struct or1k_thread_state_t {
- unsigned int __r[32];
- };
-
- or1k_thread_state_t _registers;
-};
-
-inline Registers_or1k::Registers_or1k(const void *registers) {
- static_assert(sizeof(Registers_or1k) < sizeof(unw_context_t),
- "or1k registers do not fit into unw_context_t");
- memcpy(&_registers, static_cast<const uint8_t *>(registers),
- sizeof(_registers));
-}
-
-inline Registers_or1k::Registers_or1k() {
- memset(&_registers, 0, sizeof(_registers));
-}
-
-inline bool Registers_or1k::validRegister(int regNum) const {
- if (regNum == UNW_REG_IP)
- return true;
- if (regNum == UNW_REG_SP)
- return true;
- if (regNum < 0)
- return false;
- if (regNum <= UNW_OR1K_R31)
- return true;
- return false;
-}
-
-inline uint32_t Registers_or1k::getRegister(int regNum) const {
- if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
- return _registers.__r[regNum - UNW_OR1K_R0];
-
- switch (regNum) {
- case UNW_REG_IP:
- return _registers.__r[9];
- case UNW_REG_SP:
- return _registers.__r[1];
- }
- _LIBUNWIND_ABORT("unsupported or1k register");
-}
-
-inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
- if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
- _registers.__r[regNum - UNW_OR1K_R0] = value;
- return;
- }
-
- switch (regNum) {
- case UNW_REG_IP:
- _registers.__r[9] = value;
- return;
- case UNW_REG_SP:
- _registers.__r[1] = value;
- return;
- }
- _LIBUNWIND_ABORT("unsupported or1k register");
-}
-
-inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
- return false;
-}
-
-inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
- _LIBUNWIND_ABORT("or1k float support not implemented");
-}
-
-inline void Registers_or1k::setFloatRegister(int /* regNum */,
- double /* value */) {
- _LIBUNWIND_ABORT("or1k float support not implemented");
-}
-
-inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
- return false;
-}
-
-inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
- _LIBUNWIND_ABORT("or1k vector support not implemented");
-}
-
-inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
- _LIBUNWIND_ABORT("or1k vector support not implemented");
-}
-
-inline const char *Registers_or1k::getRegisterName(int regNum) {
- switch (regNum) {
- case UNW_OR1K_R0:
- return "r0";
- case UNW_OR1K_R1:
- return "r1";
- case UNW_OR1K_R2:
- return "r2";
- case UNW_OR1K_R3:
- return "r3";
- case UNW_OR1K_R4:
- return "r4";
- case UNW_OR1K_R5:
- return "r5";
- case UNW_OR1K_R6:
- return "r6";
- case UNW_OR1K_R7:
- return "r7";
- case UNW_OR1K_R8:
- return "r8";
- case UNW_OR1K_R9:
- return "r9";
- case UNW_OR1K_R10:
- return "r10";
- case UNW_OR1K_R11:
- return "r11";
- case UNW_OR1K_R12:
- return "r12";
- case UNW_OR1K_R13:
- return "r13";
- case UNW_OR1K_R14:
- return "r14";
- case UNW_OR1K_R15:
- return "r15";
- case UNW_OR1K_R16:
- return "r16";
- case UNW_OR1K_R17:
- return "r17";
- case UNW_OR1K_R18:
- return "r18";
- case UNW_OR1K_R19:
- return "r19";
- case UNW_OR1K_R20:
- return "r20";
- case UNW_OR1K_R21:
- return "r21";
- case UNW_OR1K_R22:
- return "r22";
- case UNW_OR1K_R23:
- return "r23";
- case UNW_OR1K_R24:
- return "r24";
- case UNW_OR1K_R25:
- return "r25";
- case UNW_OR1K_R26:
- return "r26";
- case UNW_OR1K_R27:
- return "r27";
- case UNW_OR1K_R28:
- return "r28";
- case UNW_OR1K_R29:
- return "r29";
- case UNW_OR1K_R30:
- return "r30";
- case UNW_OR1K_R31:
- return "r31";
- default:
- return "unknown register";
- }
-
-}
-} // namespace libunwind
-
-#endif // __REGISTERS_HPP__
Index: contrib/llvm/projects/libunwind/src/Unwind-EHABI.h
===================================================================
--- contrib/llvm/projects/libunwind/src/Unwind-EHABI.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===------------------------- Unwind-EHABI.hpp ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __UNWIND_EHABI_H__
-#define __UNWIND_EHABI_H__
-
-#include <__libunwind_config.h>
-
-#if _LIBUNWIND_ARM_EHABI
-
-#include <stdint.h>
-#include <unwind.h>
-
-// Unable to unwind in the ARM index table (section 5 EHABI).
-#define UNW_EXIDX_CANTUNWIND 0x1
-
-static inline uint32_t signExtendPrel31(uint32_t data) {
- return data | ((data & 0x40000000u) << 1);
-}
-
-static inline uint32_t readPrel31(const uint32_t *data) {
- return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data));
-}
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
- _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
-
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
- _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
-
-extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
- _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
-
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-#endif // _LIBUNWIND_ARM_EHABI
-
-#endif // __UNWIND_EHABI_H__
Index: contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp
===================================================================
--- contrib/llvm/projects/libunwind/src/Unwind-EHABI.cpp
+++ /dev/null
@@ -1,1009 +0,0 @@
-//===--------------------------- 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 <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <type_traits>
-
-#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<const uint8_t*>(data);
- return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];
-}
-
-const char* getNextWord(const char* data, uint32_t* out) {
- *out = *reinterpret_cast<const uint32_t*>(data);
- return data + 4;
-}
-
-const char* getNextNibble(const char* data, uint32_t* out) {
- *out = *reinterpret_cast<const uint16_t*>(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<Descriptor::Kind>((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<const std::type_info *>(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<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);
-
- const char *lsda =
- reinterpret_cast<const char *>(_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<unw_cursor_t*>(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<Descriptor::Format>((*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<uint8_t>(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<uint8_t>(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<uint8_t>(((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, _Unwind_Exception *exception_object) {
- // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
- // phase 1 and then restoring it to the "primary VRS" for phase 2. The
- // effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
- // In this implementation, the phases don't share the VRS backing store.
- // Instead, they are passed the original |uc| and they create a new VRS
- // from scratch thus achieving the same effect.
- unw_cursor_t cursor1;
- unw_init_local(&cursor1, uc);
-
- // Walk each frame looking for a place to stop.
- for (bool handlerNotFound = true; handlerNotFound;) {
-
-#if !_LIBUNWIND_ARM_EHABI
- // Ask libuwind to get next frame (skip over first which is
- // _Unwind_RaiseException).
- int stepResult = unw_step(&cursor1);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- static_cast<void *>(exception_object));
- return _URC_END_OF_STACK;
- } else if (stepResult < 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE1_ERROR;
- }
-#endif
-
- // See if frame has code to run (has personality routine).
- unw_proc_info_t frameInfo;
- if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
- static_cast<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(&cursor1, functionBuf, sizeof(functionBuf),
- &offset) != UNW_ESUCCESS) ||
- (frameInfo.start_ip + offset > frameInfo.end_ip))
- functionName = ".anonymous.";
- unw_word_t pc;
- unw_get_reg(&cursor1, UNW_REG_IP, &pc);
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, "
- "lsda=0x%llX, personality=0x%llX\n",
- static_cast<void *>(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",
- static_cast<void *>(exception_object),
- reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));
- struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1);
- 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",
- static_cast<void *>(exception_object), personalityResult,
- exception_object->pr_cache.fnstart,
- static_cast<void *>(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",
- static_cast<void *>(exception_object));
- return _URC_NO_REASON;
-
- case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
- static_cast<void *>(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",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE1_ERROR;
- }
- }
- }
- return _URC_NO_REASON;
-}
-
-static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc,
- _Unwind_Exception *exception_object,
- bool resume) {
- // See comment at the start of unwind_phase1 regarding VRS integrity.
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
-
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
- static_cast<void *>(exception_object));
- int frame_count = 0;
-
- // Walk each frame until we reach where search phase said to stop.
- while (true) {
- // Ask libuwind to get next frame (skip over first which is
- // _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(&cursor2, UNW_REG_IP,
- exception_object->unwinder_cache.reserved2);
- resume = false;
- }
-
-#if !_LIBUNWIND_ARM_EHABI
- int stepResult = unw_step(&cursor2);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- static_cast<void *>(exception_object));
- return _URC_END_OF_STACK;
- } else if (stepResult < 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
- "_URC_FATAL_PHASE1_ERROR\n",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE2_ERROR;
- }
-#endif
-
- // Get info about this frame.
- unw_word_t sp;
- unw_proc_info_t frameInfo;
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
- static_cast<void *>(exception_object));
- return _URC_FATAL_PHASE2_ERROR;
- }
-
- // When tracing, print state information.
- if (_LIBUNWIND_TRACING_UNWINDING) {
- char functionBuf[512];
- const char *functionName = functionBuf;
- unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
- &offset) != UNW_ESUCCESS) ||
- (frameInfo.start_ip + offset > frameInfo.end_ip))
- functionName = ".anonymous.";
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
- "lsda=0x%llX, personality=0x%llX\n",
- static_cast<void *>(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 *)(&cursor2);
- // 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",
- static_cast<void *>(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",
- static_cast<void *>(exception_object));
- // Personality routine says to transfer control to landing pad.
- // We may get control back if landing pad calls _Unwind_Resume().
- if (_LIBUNWIND_TRACING_UNWINDING) {
- unw_word_t pc;
- unw_get_reg(&cursor2, UNW_REG_IP, &pc);
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
- "user code with ip=0x%llX, sp=0x%llX\n",
- static_cast<void *>(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(&cursor2, UNW_REG_IP, &pc);
- exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
- }
- unw_resume(&cursor2);
- // 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",
- static_cast<void *>(exception_object));
- unw_context_t uc;
- 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, exception_object);
- if (phase1 != _URC_NO_REASON)
- return phase1;
-
- // phase 2: the clean up phase
- return unwind_phase2(&uc, 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",
- static_cast<void *>(exception_object));
- unw_context_t uc;
- unw_getcontext(&uc);
-
- // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
- // which is in the same position as private_1 below.
- // TODO(ajwong): Who wronte the above? Why is it true?
- unwind_phase2(&uc, exception_object, true);
-
- // 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",
- static_cast<void *>(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",
- static_cast<void *>(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",
- static_cast<void *>(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",
- static_cast<void *>(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<uint32_t>(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",
- static_cast<void *>(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",
- static_cast<void *>(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: contrib/llvm/projects/libunwind/src/Unwind-sjlj.c
===================================================================
--- contrib/llvm/projects/libunwind/src/Unwind-sjlj.c
+++ /dev/null
@@ -1,468 +0,0 @@
-//===--------------------------- 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 <unwind.h>
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#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);
-
- // 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",
- exception_object);
- return _URC_END_OF_STACK;
- }
-
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p\n", 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",
- 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);
- return _URC_NO_REASON;
-
- case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
- "_URC_CONTINUE_UNWIND\n", exception_object);
- // continue unwinding
- break;
-
- default:
- // something went wrong
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
- 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);
-
- // 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",
- 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",
- 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",
- 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",
- 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",
- 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",
- exception_object, stopResult);
- if (stopResult != _URC_NO_REASON) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "stopped by stop function\n",
- 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",
- 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",
- 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",
- 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",
- 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",
- 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);
-
- // 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);
-
- 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",
- 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);
- 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",
- 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"
- , 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,
- 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",
- 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",
- 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);
- 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",
- 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_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_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);
- 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: contrib/llvm/projects/libunwind/src/UnwindCursor.hpp
===================================================================
--- contrib/llvm/projects/libunwind/src/UnwindCursor.hpp
+++ /dev/null
@@ -1,1344 +0,0 @@
-//===------------------------- 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
-//===----------------------------------------------------------------------===//
-
-#ifndef __UNWINDCURSOR_HPP__
-#define __UNWINDCURSOR_HPP__
-
-#include <algorithm>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <unwind.h>
-
-#ifdef __APPLE__
- #include <mach-o/dyld.h>
-#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 <typename A>
-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 A>
-typename DwarfFDECache<A>::entry *
-DwarfFDECache<A>::_buffer = _initialBuffer;
-
-template <typename A>
-typename DwarfFDECache<A>::entry *
-DwarfFDECache<A>::_bufferUsed = _initialBuffer;
-
-template <typename A>
-typename DwarfFDECache<A>::entry *
-DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
-
-template <typename A>
-typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
-
-template <typename A>
-pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
-
-#ifdef __APPLE__
-template <typename A>
-bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
-#endif
-
-template <typename A>
-typename A::pint_t DwarfFDECache<A>::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 <typename A>
-void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
- pint_t fde) {
-#if !defined(_LIBUNWIND_NO_HEAP)
- _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
- if (_bufferUsed >= _bufferEnd) {
- size_t oldSize = (size_t)(_bufferEnd - _buffer);
- 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 <typename A>
-void DwarfFDECache<A>::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 <typename A>
-void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
- removeAllIn((pint_t) mh);
-}
-#endif
-
-template <typename A>
-void DwarfFDECache<A>::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 <typename A> 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 <typename A> 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 <typename A> 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 <typename A> 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 <typename A> 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 <typename A> 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 <typename A> 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 <typename A, typename R>
-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 &sects);
-
- 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<const uint32_t *>(_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 &sects,
- uint32_t fdeSectionOffsetHint=0);
- int stepWithDwarfFDE() {
- return DwarfInstructions<A, R>::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 &sects);
- int stepWithCompactEncoding() {
- #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
- if ( compactSaysUseDwarf() )
- return stepWithDwarfFDE();
- #endif
- R dummy;
- return stepWithCompactEncoding(dummy);
- }
-
- int stepWithCompactEncoding(Registers_x86_64 &) {
- return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
- _info.format, _info.start_ip, _addressSpace, _registers);
- }
-
- int stepWithCompactEncoding(Registers_x86 &) {
- return CompactUnwinder_x86<A>::stepWithCompactEncoding(
- _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
- }
-
- int stepWithCompactEncoding(Registers_ppc &) {
- return UNW_EINVAL;
- }
-
- int stepWithCompactEncoding(Registers_arm64 &) {
- return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
- _info.format, _info.start_ip, _addressSpace, _registers);
- }
-
- bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
- R dummy;
- return compactSaysUseDwarf(dummy, offset);
- }
-
- 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;
- }
-
- 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;
- }
-
- bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
- return true;
- }
-
- 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 // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
-
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
- compact_unwind_encoding_t dwarfEncoding() const {
- R dummy;
- return dwarfEncoding(dummy);
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
- return UNWIND_X86_64_MODE_DWARF;
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
- return UNWIND_X86_MODE_DWARF;
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
- return 0;
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
- return UNWIND_ARM64_MODE_DWARF;
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
- return 0;
- }
-
- compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {
- return 0;
- }
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
-
-
- A &_addressSpace;
- R _registers;
- unw_proc_info_t _info;
- bool _unwindInfoMissing;
- bool _isSignalFrame;
-};
-
-
-template <typename A, typename R>
-UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
- : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
- _isSignalFrame(false) {
- static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t),
- "UnwindCursor<> does not fit in unw_cursor_t");
- memset(&_info, 0, sizeof(_info));
-}
-
-template <typename A, typename R>
-UnwindCursor<A, R>::UnwindCursor(A &as, void *)
- : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
- memset(&_info, 0, sizeof(_info));
- // FIXME
- // fill in _registers from thread arg
-}
-
-
-template <typename A, typename R>
-bool UnwindCursor<A, R>::validReg(int regNum) {
- return _registers.validRegister(regNum);
-}
-
-template <typename A, typename R>
-unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
- return _registers.getRegister(regNum);
-}
-
-template <typename A, typename R>
-void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
- _registers.setRegister(regNum, (typename A::pint_t)value);
-}
-
-template <typename A, typename R>
-bool UnwindCursor<A, R>::validFloatReg(int regNum) {
- return _registers.validFloatRegister(regNum);
-}
-
-template <typename A, typename R>
-unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
- return _registers.getFloatRegister(regNum);
-}
-
-template <typename A, typename R>
-void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
- _registers.setFloatRegister(regNum, value);
-}
-
-template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
- _registers.jumpto();
-}
-
-#ifdef __arm__
-template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
- _registers.saveVFPAsX();
-}
-#endif
-
-template <typename A, typename R>
-const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
- return _registers.getRegisterName(regNum);
-}
-
-template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
- return _isSignalFrame;
-}
-
-#if _LIBUNWIND_ARM_EHABI
-struct EHABIIndexEntry {
- uint32_t functionOffset;
- uint32_t data;
-};
-
-template<typename A>
-struct EHABISectionIterator {
- typedef EHABISectionIterator _Self;
-
- typedef std::random_access_iterator_tag iterator_category;
- typedef typename A::pint_t value_type;
- typedef typename A::pint_t* pointer;
- typedef typename A::pint_t& reference;
- 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(&sects) {}
-
- _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 <typename A, typename R>
-bool UnwindCursor<A, R>::getInfoFromEHABISection(
- pint_t pc,
- const UnwindInfoSections &sects) {
- EHABISectionIterator<A> begin =
- EHABISectionIterator<A>::begin(_addressSpace, sects);
- EHABISectionIterator<A> end =
- EHABISectionIterator<A>::end(_addressSpace, sects);
-
- EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
- if (itNextPC == begin || itNextPC == end)
- return false;
- EHABISectionIterator<A> 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<uint32_t*>(exceptionTableAddr) + 1;
- uint32_t FirstDataWord = *UnwindData;
- size_t N = ((FirstDataWord >> 24) & 0xff);
- size_t NDataWords = N + 1;
- lsda = reinterpret_cast<uintptr_t>(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 <typename A, typename R>
-bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
- const UnwindInfoSections &sects,
- uint32_t fdeSectionOffsetHint) {
- typename CFI_Parser<A>::FDE_Info fdeInfo;
- typename CFI_Parser<A>::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<A>::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<A>::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<A>::findFDE(sects.dso_base, pc);
- if (cachedFDE != 0) {
- foundFDE =
- CFI_Parser<A>::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<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
- (uint32_t)sects.dwarf_section_length, 0,
- &fdeInfo, &cieInfo);
- }
- if (foundFDE) {
- typename CFI_Parser<A>::PrologInfo prolog;
- if (CFI_Parser<A>::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<A>::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);
- return false;
-}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
-
-
-#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
-template <typename A, typename R>
-bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
- const UnwindInfoSections &sects) {
- 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<A> 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<A> 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<A> pageHeader(_addressSpace,
- secondLevelAddr);
- UnwindSectionRegularArray<A> 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<A> pageHeader(_addressSpace,
- secondLevelAddr);
- UnwindSectionCompressedArray<A> 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",
- (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",
- (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",
- (uint64_t) sects.compact_unwind_section);
- return false;
- }
-
- // look up LSDA, if encoding says function has one
- if (encoding & UNWIND_HAS_LSDA) {
- UnwindSectionLsdaArray<A> 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",
- 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",
- 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 <typename A, typename R>
-void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
- pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
-#if _LIBUNWIND_ARM_EHABI
- // 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<A>::findFDE(0, pc);
- if (cachedFDE != 0) {
- CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
- CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
- const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
- cachedFDE, &fdeInfo, &cieInfo);
- if (msg == NULL) {
- typename CFI_Parser<A>::PrologInfo prolog;
- if (CFI_Parser<A>::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<LocalAddressSpace>::FDE_Info fdeInfo;
- CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
- if (!CFI_Parser<A>::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<A>::PrologInfo prolog;
- if (CFI_Parser<A>::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 <typename A, typename R>
-int UnwindCursor<A, R>::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 <typename A, typename R>
-void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
- *info = _info;
-}
-
-template <typename A, typename R>
-bool UnwindCursor<A, R>::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: contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c
===================================================================
--- contrib/llvm/projects/libunwind/src/UnwindLevel1-gcc-ext.c
+++ /dev/null
@@ -1,316 +0,0 @@
-//===--------------------- 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 <inttypes.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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",
- (void *)exception_object,
- (long)exception_object->unwinder_cache.reserved1);
-#else
- _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n",
- (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_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_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);
- // 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",
- (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
- // _Unwind_Backtrace())
- if (unw_step(&cursor) <= 0) {
- _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
- "bottom of stack, returning %d\n",
- _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",
- (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);
- 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,
- (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",
- (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);
- *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);
- _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);
- _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",
- 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);
- // 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);
- // 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);
- // 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);
- // 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);
- // 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);
- // 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: contrib/llvm/projects/libunwind/src/UnwindLevel1.c
===================================================================
--- contrib/llvm/projects/libunwind/src/UnwindLevel1.c
+++ /dev/null
@@ -1,506 +0,0 @@
-//===------------------------- 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 <unwind.h>), thus we need
-// to export these functions from libunwind.so as well.
-#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "libunwind.h"
-#include "unwind.h"
-#include "config.h"
-
-#if !_LIBUNWIND_ARM_EHABI
-
-static _Unwind_Reason_Code
-unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
- unw_cursor_t cursor1;
- unw_init_local(&cursor1, uc);
-
- // 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
- // _Unwind_RaiseException).
- int stepResult = unw_step(&cursor1);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- (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",
- (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(&cursor1, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
- (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(&cursor1, functionBuf, sizeof(functionBuf),
- &offset) != UNW_ESUCCESS) ||
- (frameInfo.start_ip + offset > frameInfo.end_ip))
- functionName = ".anonymous.";
- unw_word_t pc;
- unw_get_reg(&cursor1, UNW_REG_IP, &pc);
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
- (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",
- (void *)exception_object, (void *)(uintptr_t)p);
- _Unwind_Reason_Code personalityResult =
- (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
- exception_object, (struct _Unwind_Context *)(&cursor1));
- switch (personalityResult) {
- case _URC_HANDLER_FOUND:
- // found a catch clause or locals that need destructing in this frame
- // stop search and remember stack pointer at the frame
- handlerNotFound = false;
- unw_get_reg(&cursor1, UNW_REG_SP, &sp);
- exception_object->private_2 = (uintptr_t)sp;
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
- (void *)exception_object);
- return _URC_NO_REASON;
-
- case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
- (void *)exception_object);
- // continue unwinding
- break;
-
- default:
- // something went wrong
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
- (void *)exception_object);
- return _URC_FATAL_PHASE1_ERROR;
- }
- }
- }
- return _URC_NO_REASON;
-}
-
-
-static _Unwind_Reason_Code
-unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
-
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
- (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
- // _Unwind_RaiseException).
- int stepResult = unw_step(&cursor2);
- if (stepResult == 0) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
- "bottom => _URC_END_OF_STACK\n",
- (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",
- (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(&cursor2, UNW_REG_SP, &sp);
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
- "failed => _URC_FATAL_PHASE1_ERROR\n",
- (void *)exception_object);
- return _URC_FATAL_PHASE2_ERROR;
- }
-
- // When tracing, print state information.
- if (_LIBUNWIND_TRACING_UNWINDING) {
- char functionBuf[512];
- const char *functionName = functionBuf;
- unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
- &offset) != UNW_ESUCCESS) ||
- (frameInfo.start_ip + offset > frameInfo.end_ip))
- functionName = ".anonymous.";
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIx64
- ", func=%s, sp=0x%" PRIx64 ", lsda=0x%" PRIx64
- ", personality=0x%" PRIx64 "\n",
- (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 *)(&cursor2));
- switch (personalityResult) {
- case _URC_CONTINUE_UNWIND:
- // Continue unwinding
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
- (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",
- (void *)exception_object);
- // Personality routine says to transfer control to landing pad.
- // We may get control back if landing pad calls _Unwind_Resume().
- if (_LIBUNWIND_TRACING_UNWINDING) {
- unw_word_t pc;
- unw_get_reg(&cursor2, UNW_REG_IP, &pc);
- unw_get_reg(&cursor2, UNW_REG_SP, &sp);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
- "user code with ip=0x%" PRIx64
- ", sp=0x%" PRIx64 "\n",
- (void *)exception_object, pc, sp);
- }
- unw_resume(&cursor2);
- // 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,
- _Unwind_Exception *exception_object,
- _Unwind_Stop_Fn stop, void *stop_parameter) {
- unw_cursor_t cursor2;
- unw_init_local(&cursor2, uc);
-
- // Walk each frame until we reach where search phase said to stop
- while (unw_step(&cursor2) > 0) {
-
- // Update info about this frame.
- unw_proc_info_t frameInfo;
- if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
- "failed => _URC_END_OF_STACK\n",
- (void *)exception_object);
- return _URC_FATAL_PHASE2_ERROR;
- }
-
- // When tracing, print state information.
- if (_LIBUNWIND_TRACING_UNWINDING) {
- char functionBuf[512];
- const char *functionName = functionBuf;
- unw_word_t offset;
- if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
- &offset) != UNW_ESUCCESS) ||
- (frameInfo.start_ip + offset > frameInfo.end_ip))
- functionName = ".anonymous.";
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
- (void *)exception_object, frameInfo.start_ip, functionName,
- frameInfo.lsda, frameInfo.handler);
- }
-
- // Call stop function at each frame.
- _Unwind_Action action =
- (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
- _Unwind_Reason_Code stopResult =
- (*stop)(1, action, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)(&cursor2), stop_parameter);
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
- (void *)exception_object, stopResult);
- if (stopResult != _URC_NO_REASON) {
- _LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n",
- (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",
- (void *)exception_object, (void *)(uintptr_t)p);
- _Unwind_Reason_Code personalityResult =
- (*p)(1, action, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)(&cursor2));
- switch (personalityResult) {
- case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "personality returned "
- "_URC_CONTINUE_UNWIND\n",
- (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",
- (void *)exception_object);
- // We may get control back if landing pad calls _Unwind_Resume().
- unw_resume(&cursor2);
- break;
- default:
- // Personality routine returned an unknown result code.
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
- "personality returned %d, "
- "_URC_FATAL_PHASE2_ERROR\n",
- (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",
- (void *)exception_object);
- _Unwind_Action lastAction =
- (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
- (*stop)(1, lastAction, exception_object->exception_class, exception_object,
- (struct _Unwind_Context *)(&cursor2), stop_parameter);
-
- // Clean up phase did not resume at the frame that the search phase said it
- // would.
- return _URC_FATAL_PHASE2_ERROR;
-}
-
-
-/// Called by __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",
- (void *)exception_object);
- unw_context_t uc;
- 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, exception_object);
- if (phase1 != _URC_NO_REASON)
- return phase1;
-
- // phase 2: the clean up phase
- return unwind_phase2(&uc, 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);
- unw_context_t uc;
- unw_getcontext(&uc);
-
- if (exception_object->private_1 != 0)
- unwind_phase2_forced(&uc, exception_object,
- (_Unwind_Stop_Fn) exception_object->private_1,
- (void *)exception_object->private_2);
- else
- unwind_phase2(&uc, 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",
- (void *)exception_object, (void *)(uintptr_t)stop);
- unw_context_t uc;
- unw_getcontext(&uc);
-
- // Mark that this is a forced unwind, so _Unwind_Resume() can do
- // the right thing.
- exception_object->private_1 = (uintptr_t) stop;
- exception_object->private_2 = (uintptr_t) stop_parameter;
-
- // do it
- return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
-}
-
-
-/// Called by personality handler during phase 2 to get LSDA for current frame.
-_LIBUNWIND_EXPORT uintptr_t
-_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
- 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",
- (void *)context, result);
- if (result != 0) {
- if (*((uint8_t *)result) != 0xFF)
- _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF\n",
- 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",
- (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",
- (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",
- (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",
- (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",
- (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: contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
===================================================================
--- contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
+++ /dev/null
@@ -1,485 +0,0 @@
-//===-------------------- UnwindRegistersRestore.S ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "assembly.h"
-
- .text
-
-#if defined(__i386__)
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
-#
-# void libunwind::Registers_x86::jumpto()
-#
-# On entry:
-# + +
-# +-----------------------+
-# + thread_state pointer +
-# +-----------------------+
-# + return address +
-# +-----------------------+ <-- SP
-# + +
- movl 4(%esp), %eax
- # set up eax and ret on new stack location
- movl 28(%eax), %edx # edx holds new stack pointer
- subl $8,%edx
- movl %edx, 28(%eax)
- movl 0(%eax), %ebx
- movl %ebx, 0(%edx)
- movl 40(%eax), %ebx
- movl %ebx, 4(%edx)
- # we now have ret and eax pushed onto where new stack will be
- # restore all registers
- movl 4(%eax), %ebx
- movl 8(%eax), %ecx
- movl 12(%eax), %edx
- movl 16(%eax), %edi
- movl 20(%eax), %esi
- movl 24(%eax), %ebp
- movl 28(%eax), %esp
- # skip ss
- # skip eflags
- pop %eax # eax was already pushed on new stack
- ret # eip was already pushed on new stack
- # skip cs
- # skip ds
- # skip es
- # skip fs
- # skip gs
-
-#elif defined(__x86_64__)
-
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
-#
-# void libunwind::Registers_x86_64::jumpto()
-#
-# On entry, thread_state pointer is in rdi
-
- movq 56(%rdi), %rax # rax holds new stack pointer
- subq $16, %rax
- movq %rax, 56(%rdi)
- movq 32(%rdi), %rbx # store new rdi on new stack
- movq %rbx, 0(%rax)
- movq 128(%rdi), %rbx # store new rip on new stack
- movq %rbx, 8(%rax)
- # restore all registers
- movq 0(%rdi), %rax
- movq 8(%rdi), %rbx
- movq 16(%rdi), %rcx
- movq 24(%rdi), %rdx
- # restore rdi later
- movq 40(%rdi), %rsi
- movq 48(%rdi), %rbp
- # restore rsp later
- movq 64(%rdi), %r8
- movq 72(%rdi), %r9
- movq 80(%rdi), %r10
- movq 88(%rdi), %r11
- movq 96(%rdi), %r12
- movq 104(%rdi), %r13
- movq 112(%rdi), %r14
- movq 120(%rdi), %r15
- # skip rflags
- # skip cs
- # skip fs
- # skip gs
- movq 56(%rdi), %rsp # cut back rsp to new location
- pop %rdi # rdi was saved here earlier
- ret # rip was saved here
-
-
-#elif defined(__ppc__)
-
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
-;
-; void libunwind::Registers_ppc::jumpto()
-;
-; On entry:
-; thread_state pointer is in r3
-;
-
- ; restore integral registerrs
- ; skip r0 for now
- ; skip r1 for now
- lwz r2, 16(r3)
- ; skip r3 for now
- ; skip r4 for now
- ; skip r5 for now
- lwz r6, 32(r3)
- lwz r7, 36(r3)
- lwz r8, 40(r3)
- lwz r9, 44(r3)
- lwz r10, 48(r3)
- lwz r11, 52(r3)
- lwz r12, 56(r3)
- lwz r13, 60(r3)
- lwz r14, 64(r3)
- lwz r15, 68(r3)
- lwz r16, 72(r3)
- lwz r17, 76(r3)
- lwz r18, 80(r3)
- lwz r19, 84(r3)
- lwz r20, 88(r3)
- lwz r21, 92(r3)
- lwz r22, 96(r3)
- lwz r23,100(r3)
- lwz r24,104(r3)
- lwz r25,108(r3)
- lwz r26,112(r3)
- lwz r27,116(r3)
- lwz r28,120(r3)
- lwz r29,124(r3)
- lwz r30,128(r3)
- lwz r31,132(r3)
-
- ; restore float registers
- lfd f0, 160(r3)
- lfd f1, 168(r3)
- lfd f2, 176(r3)
- lfd f3, 184(r3)
- lfd f4, 192(r3)
- lfd f5, 200(r3)
- lfd f6, 208(r3)
- lfd f7, 216(r3)
- lfd f8, 224(r3)
- lfd f9, 232(r3)
- lfd f10,240(r3)
- lfd f11,248(r3)
- lfd f12,256(r3)
- lfd f13,264(r3)
- lfd f14,272(r3)
- lfd f15,280(r3)
- lfd f16,288(r3)
- lfd f17,296(r3)
- lfd f18,304(r3)
- lfd f19,312(r3)
- lfd f20,320(r3)
- lfd f21,328(r3)
- lfd f22,336(r3)
- lfd f23,344(r3)
- lfd f24,352(r3)
- lfd f25,360(r3)
- lfd f26,368(r3)
- lfd f27,376(r3)
- lfd f28,384(r3)
- lfd f29,392(r3)
- lfd f30,400(r3)
- lfd f31,408(r3)
-
- ; restore vector registers if any are in use
- lwz r5,156(r3) ; test VRsave
- cmpwi r5,0
- beq Lnovec
-
- subi r4,r1,16
- rlwinm r4,r4,0,0,27 ; mask low 4-bits
- ; r4 is now a 16-byte aligned pointer into the red zone
- ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
-
-
-#define LOAD_VECTOR_UNALIGNEDl(_index) \
- andis. r0,r5,(1<<(15-_index)) @\
- beq Ldone ## _index @\
- lwz r0, 424+_index*16(r3) @\
- stw r0, 0(r4) @\
- lwz r0, 424+_index*16+4(r3) @\
- stw r0, 4(r4) @\
- lwz r0, 424+_index*16+8(r3) @\
- stw r0, 8(r4) @\
- lwz r0, 424+_index*16+12(r3)@\
- stw r0, 12(r4) @\
- lvx v ## _index,0,r4 @\
-Ldone ## _index:
-
-#define LOAD_VECTOR_UNALIGNEDh(_index) \
- andi. r0,r5,(1<<(31-_index)) @\
- beq Ldone ## _index @\
- lwz r0, 424+_index*16(r3) @\
- stw r0, 0(r4) @\
- lwz r0, 424+_index*16+4(r3) @\
- stw r0, 4(r4) @\
- lwz r0, 424+_index*16+8(r3) @\
- stw r0, 8(r4) @\
- lwz r0, 424+_index*16+12(r3)@\
- stw r0, 12(r4) @\
- lvx v ## _index,0,r4 @\
- Ldone ## _index:
-
-
- LOAD_VECTOR_UNALIGNEDl(0)
- LOAD_VECTOR_UNALIGNEDl(1)
- LOAD_VECTOR_UNALIGNEDl(2)
- LOAD_VECTOR_UNALIGNEDl(3)
- LOAD_VECTOR_UNALIGNEDl(4)
- LOAD_VECTOR_UNALIGNEDl(5)
- LOAD_VECTOR_UNALIGNEDl(6)
- LOAD_VECTOR_UNALIGNEDl(7)
- LOAD_VECTOR_UNALIGNEDl(8)
- LOAD_VECTOR_UNALIGNEDl(9)
- LOAD_VECTOR_UNALIGNEDl(10)
- LOAD_VECTOR_UNALIGNEDl(11)
- LOAD_VECTOR_UNALIGNEDl(12)
- LOAD_VECTOR_UNALIGNEDl(13)
- LOAD_VECTOR_UNALIGNEDl(14)
- LOAD_VECTOR_UNALIGNEDl(15)
- LOAD_VECTOR_UNALIGNEDh(16)
- LOAD_VECTOR_UNALIGNEDh(17)
- LOAD_VECTOR_UNALIGNEDh(18)
- LOAD_VECTOR_UNALIGNEDh(19)
- LOAD_VECTOR_UNALIGNEDh(20)
- LOAD_VECTOR_UNALIGNEDh(21)
- LOAD_VECTOR_UNALIGNEDh(22)
- LOAD_VECTOR_UNALIGNEDh(23)
- LOAD_VECTOR_UNALIGNEDh(24)
- LOAD_VECTOR_UNALIGNEDh(25)
- LOAD_VECTOR_UNALIGNEDh(26)
- LOAD_VECTOR_UNALIGNEDh(27)
- LOAD_VECTOR_UNALIGNEDh(28)
- LOAD_VECTOR_UNALIGNEDh(29)
- LOAD_VECTOR_UNALIGNEDh(30)
- LOAD_VECTOR_UNALIGNEDh(31)
-
-Lnovec:
- lwz r0, 136(r3) ; __cr
- mtocrf 255,r0
- lwz r0, 148(r3) ; __ctr
- mtctr r0
- lwz r0, 0(r3) ; __ssr0
- mtctr r0
- lwz r0, 8(r3) ; do r0 now
- lwz r5,28(r3) ; do r5 now
- lwz r4,24(r3) ; do r4 now
- lwz r1,12(r3) ; do sp now
- lwz r3,20(r3) ; do r3 last
- bctr
-
-#elif defined(__arm64__) || defined(__aarch64__)
-
-//
-// void libunwind::Registers_arm64::jumpto()
-//
-// On entry:
-// thread_state pointer is in x0
-//
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
- // skip restore of x0,x1 for now
- ldp x2, x3, [x0, #0x010]
- ldp x4, x5, [x0, #0x020]
- ldp x6, x7, [x0, #0x030]
- ldp x8, x9, [x0, #0x040]
- ldp x10,x11, [x0, #0x050]
- ldp x12,x13, [x0, #0x060]
- ldp x14,x15, [x0, #0x070]
- ldp x16,x17, [x0, #0x080]
- ldp x18,x19, [x0, #0x090]
- ldp x20,x21, [x0, #0x0A0]
- ldp x22,x23, [x0, #0x0B0]
- ldp x24,x25, [x0, #0x0C0]
- ldp x26,x27, [x0, #0x0D0]
- ldp x28,fp, [x0, #0x0E0]
- ldr lr, [x0, #0x100] // restore pc into lr
- ldr x1, [x0, #0x0F8]
- mov sp,x1 // restore sp
-
- ldp d0, d1, [x0, #0x110]
- ldp d2, d3, [x0, #0x120]
- ldp d4, d5, [x0, #0x130]
- ldp d6, d7, [x0, #0x140]
- ldp d8, d9, [x0, #0x150]
- ldp d10,d11, [x0, #0x160]
- ldp d12,d13, [x0, #0x170]
- ldp d14,d15, [x0, #0x180]
- ldp d16,d17, [x0, #0x190]
- ldp d18,d19, [x0, #0x1A0]
- ldp d20,d21, [x0, #0x1B0]
- ldp d22,d23, [x0, #0x1C0]
- ldp d24,d25, [x0, #0x1D0]
- ldp d26,d27, [x0, #0x1E0]
- ldp d28,d29, [x0, #0x1F0]
- ldr d30, [x0, #0x200]
- ldr d31, [x0, #0x208]
-
- ldp x0, x1, [x0, #0x000] // restore x0,x1
- ret lr // jump to pc
-
-#elif defined(__arm__) && !defined(__APPLE__)
-
-#if !defined(__ARM_ARCH_ISA_ARM)
- .thumb
-#endif
-
-@
-@ void libunwind::Registers_arm::restoreCoreAndJumpTo()
-@
-@ On entry:
-@ thread_state pointer is in r0
-@
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
-#if !defined(__ARM_ARCH_ISA_ARM)
- ldr r2, [r0, #52]
- ldr r3, [r0, #60]
- mov sp, r2
- mov lr, r3 @ restore pc into lr
- ldm r0, {r0-r7}
-#else
- @ Use lr as base so that r0 can be restored.
- mov lr, r0
- @ 32bit thumb-2 restrictions for ldm:
- @ . the sp (r13) cannot be in the list
- @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction
- ldm lr, {r0-r12}
- ldr sp, [lr, #52]
- ldr lr, [lr, #60] @ restore pc into lr
-#endif
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3-d16
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
- @ VFP and iwMMX instructions are only available when compiling with the flags
- @ that enable them. We do not want to do that in the library (because we do not
- @ want the compiler to generate instructions that access those) but this is
- @ only accessed if the personality routine needs these registers. Use of
- @ these registers implies they are, actually, available on the target, so
- @ it's ok to execute.
- @ So, generate the instruction using the corresponding coprocessor mnemonic.
- vldmia r0, {d0-d15}
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3-d16
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
- vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
- vldmia r0, {d16-d31}
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
- ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8
- ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8
- ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8
- ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8
- ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8
- ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8
- ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8
- ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8
- ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8
- ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8
- ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8
- ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8
- ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8
- ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8
- ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8
- ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8
-#endif
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
- ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4
- ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4
- ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4
- ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4
-#endif
- JMP(lr)
-
-#elif defined(__or1k__)
-
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
-#
-# void libunwind::Registers_or1k::jumpto()
-#
-# On entry:
-# thread_state pointer is in r3
-#
-
- # restore integral registerrs
- l.lwz r0, 0(r3)
- l.lwz r1, 4(r3)
- l.lwz r2, 8(r3)
- # skip r3 for now
- l.lwz r4, 16(r3)
- l.lwz r5, 20(r3)
- l.lwz r6, 24(r3)
- l.lwz r7, 28(r3)
- l.lwz r8, 32(r3)
- l.lwz r9, 36(r3)
- l.lwz r10, 40(r3)
- l.lwz r11, 44(r3)
- l.lwz r12, 48(r3)
- l.lwz r13, 52(r3)
- l.lwz r14, 56(r3)
- l.lwz r15, 60(r3)
- l.lwz r16, 64(r3)
- l.lwz r17, 68(r3)
- l.lwz r18, 72(r3)
- l.lwz r19, 76(r3)
- l.lwz r20, 80(r3)
- l.lwz r21, 84(r3)
- l.lwz r22, 88(r3)
- l.lwz r23, 92(r3)
- l.lwz r24, 96(r3)
- l.lwz r25,100(r3)
- l.lwz r26,104(r3)
- l.lwz r27,108(r3)
- l.lwz r28,112(r3)
- l.lwz r29,116(r3)
- l.lwz r30,120(r3)
- l.lwz r31,124(r3)
-
- # at last, restore r3
- l.lwz r3, 12(r3)
-
- # jump to pc
- l.jr r9
- l.nop
-
-#elif defined(__riscv__)
-
-/* RISCVTODO */
-
-#endif
Index: contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S
===================================================================
--- contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S
+++ /dev/null
@@ -1,471 +0,0 @@
-//===------------------------ UnwindRegistersSave.S -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "assembly.h"
-
- .text
-
-#if defined(__i386__)
-
-#
-# extern int unw_getcontext(unw_context_t* thread_state)
-#
-# On entry:
-# + +
-# +-----------------------+
-# + thread_state pointer +
-# +-----------------------+
-# + return address +
-# +-----------------------+ <-- SP
-# + +
-#
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- push %eax
- movl 8(%esp), %eax
- movl %ebx, 4(%eax)
- movl %ecx, 8(%eax)
- movl %edx, 12(%eax)
- movl %edi, 16(%eax)
- movl %esi, 20(%eax)
- movl %ebp, 24(%eax)
- movl %esp, %edx
- addl $8, %edx
- movl %edx, 28(%eax) # store what sp was at call site as esp
- # skip ss
- # skip eflags
- movl 4(%esp), %edx
- movl %edx, 40(%eax) # store return address as eip
- # skip cs
- # skip ds
- # skip es
- # skip fs
- # skip gs
- movl (%esp), %edx
- movl %edx, (%eax) # store original eax
- popl %eax
- xorl %eax, %eax # return UNW_ESUCCESS
- ret
-
-#elif defined(__x86_64__)
-
-#
-# extern int unw_getcontext(unw_context_t* thread_state)
-#
-# On entry:
-# thread_state pointer is in rdi
-#
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- movq %rax, (%rdi)
- movq %rbx, 8(%rdi)
- movq %rcx, 16(%rdi)
- movq %rdx, 24(%rdi)
- movq %rdi, 32(%rdi)
- movq %rsi, 40(%rdi)
- movq %rbp, 48(%rdi)
- movq %rsp, 56(%rdi)
- addq $8, 56(%rdi)
- movq %r8, 64(%rdi)
- movq %r9, 72(%rdi)
- movq %r10, 80(%rdi)
- movq %r11, 88(%rdi)
- movq %r12, 96(%rdi)
- movq %r13,104(%rdi)
- movq %r14,112(%rdi)
- movq %r15,120(%rdi)
- movq (%rsp),%rsi
- movq %rsi,128(%rdi) # store return address as rip
- # skip rflags
- # skip cs
- # skip fs
- # skip gs
- xorl %eax, %eax # return UNW_ESUCCESS
- ret
-
-# elif defined(__mips__)
-
-#
-# extern int unw_getcontext(unw_context_t* thread_state)
-#
-# Just trap for the time being.
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- teq $0, $0
-
-#elif defined(__ppc__)
-
-;
-; extern int unw_getcontext(unw_context_t* thread_state)
-;
-; On entry:
-; thread_state pointer is in r3
-;
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- stw r0, 8(r3)
- mflr r0
- stw r0, 0(r3) ; store lr as ssr0
- stw r1, 12(r3)
- stw r2, 16(r3)
- stw r3, 20(r3)
- stw r4, 24(r3)
- stw r5, 28(r3)
- stw r6, 32(r3)
- stw r7, 36(r3)
- stw r8, 40(r3)
- stw r9, 44(r3)
- stw r10, 48(r3)
- stw r11, 52(r3)
- stw r12, 56(r3)
- stw r13, 60(r3)
- stw r14, 64(r3)
- stw r15, 68(r3)
- stw r16, 72(r3)
- stw r17, 76(r3)
- stw r18, 80(r3)
- stw r19, 84(r3)
- stw r20, 88(r3)
- stw r21, 92(r3)
- stw r22, 96(r3)
- stw r23,100(r3)
- stw r24,104(r3)
- stw r25,108(r3)
- stw r26,112(r3)
- stw r27,116(r3)
- stw r28,120(r3)
- stw r29,124(r3)
- stw r30,128(r3)
- stw r31,132(r3)
-
- ; save VRSave register
- mfspr r0,256
- stw r0,156(r3)
- ; save CR registers
- mfcr r0
- stw r0,136(r3)
- ; save CTR register
- mfctr r0
- stw r0,148(r3)
-
- ; save float registers
- stfd f0, 160(r3)
- stfd f1, 168(r3)
- stfd f2, 176(r3)
- stfd f3, 184(r3)
- stfd f4, 192(r3)
- stfd f5, 200(r3)
- stfd f6, 208(r3)
- stfd f7, 216(r3)
- stfd f8, 224(r3)
- stfd f9, 232(r3)
- stfd f10,240(r3)
- stfd f11,248(r3)
- stfd f12,256(r3)
- stfd f13,264(r3)
- stfd f14,272(r3)
- stfd f15,280(r3)
- stfd f16,288(r3)
- stfd f17,296(r3)
- stfd f18,304(r3)
- stfd f19,312(r3)
- stfd f20,320(r3)
- stfd f21,328(r3)
- stfd f22,336(r3)
- stfd f23,344(r3)
- stfd f24,352(r3)
- stfd f25,360(r3)
- stfd f26,368(r3)
- stfd f27,376(r3)
- stfd f28,384(r3)
- stfd f29,392(r3)
- stfd f30,400(r3)
- stfd f31,408(r3)
-
-
- ; save vector registers
-
- subi r4,r1,16
- rlwinm r4,r4,0,0,27 ; mask low 4-bits
- ; r4 is now a 16-byte aligned pointer into the red zone
-
-#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
- stvx _vec,0,r4 @\
- lwz r5, 0(r4) @\
- stw r5, _offset(r3) @\
- lwz r5, 4(r4) @\
- stw r5, _offset+4(r3) @\
- lwz r5, 8(r4) @\
- stw r5, _offset+8(r3) @\
- lwz r5, 12(r4) @\
- stw r5, _offset+12(r3)
-
- SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
- SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
- SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
- SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
- SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
- SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
- SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
- SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
- SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
- SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
- SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
- SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
- SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
- SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
- SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
- SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
- SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
- SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
- SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
- SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
- SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
- SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
- SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
- SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
- SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
- SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
- SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
- SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
- SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
- SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
- SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
- SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
-
- li r3, 0 ; return UNW_ESUCCESS
- blr
-
-
-#elif defined(__arm64__) || defined(__aarch64__)
-
-//
-// extern int unw_getcontext(unw_context_t* thread_state)
-//
-// On entry:
-// thread_state pointer is in x0
-//
- .p2align 2
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- stp x0, x1, [x0, #0x000]
- stp x2, x3, [x0, #0x010]
- stp x4, x5, [x0, #0x020]
- stp x6, x7, [x0, #0x030]
- stp x8, x9, [x0, #0x040]
- stp x10,x11, [x0, #0x050]
- stp x12,x13, [x0, #0x060]
- stp x14,x15, [x0, #0x070]
- stp x16,x17, [x0, #0x080]
- stp x18,x19, [x0, #0x090]
- stp x20,x21, [x0, #0x0A0]
- stp x22,x23, [x0, #0x0B0]
- stp x24,x25, [x0, #0x0C0]
- stp x26,x27, [x0, #0x0D0]
- stp x28,fp, [x0, #0x0E0]
- str lr, [x0, #0x0F0]
- mov x1,sp
- str x1, [x0, #0x0F8]
- str lr, [x0, #0x100] // store return address as pc
- // skip cpsr
- stp d0, d1, [x0, #0x110]
- stp d2, d3, [x0, #0x120]
- stp d4, d5, [x0, #0x130]
- stp d6, d7, [x0, #0x140]
- stp d8, d9, [x0, #0x150]
- stp d10,d11, [x0, #0x160]
- stp d12,d13, [x0, #0x170]
- stp d14,d15, [x0, #0x180]
- stp d16,d17, [x0, #0x190]
- stp d18,d19, [x0, #0x1A0]
- stp d20,d21, [x0, #0x1B0]
- stp d22,d23, [x0, #0x1C0]
- stp d24,d25, [x0, #0x1D0]
- stp d26,d27, [x0, #0x1E0]
- stp d28,d29, [x0, #0x1F0]
- str d30, [x0, #0x200]
- str d31, [x0, #0x208]
- mov x0, #0 // return UNW_ESUCCESS
- ret
-
-#elif defined(__arm__) && !defined(__APPLE__)
-
-#if !defined(__ARM_ARCH_ISA_ARM)
- .thumb
-#endif
-
-@
-@ extern int unw_getcontext(unw_context_t* thread_state)
-@
-@ On entry:
-@ thread_state pointer is in r0
-@
-@ Per EHABI #4.7 this only saves the core integer registers.
-@ EHABI #7.4.5 notes that in general all VRS registers should be restored
-@ however this is very hard to do for VFP registers because it is unknown
-@ to the library how many registers are implemented by the architecture.
-@ Instead, VFP registers are demand saved by logic external to unw_getcontext.
-@
- .p2align 2
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
-#if !defined(__ARM_ARCH_ISA_ARM)
- stm r0, {r0-r7}
- mov r2, sp
- mov r3, lr
- str r2, [r0, #52]
- str r3, [r0, #56]
- str r3, [r0, #60] @ store return address as pc
-#else
- @ 32bit thumb-2 restrictions for stm:
- @ . the sp (r13) cannot be in the list
- @ . the pc (r15) cannot be in the list in an STM instruction
- stm r0, {r0-r12}
- str sp, [r0, #52]
- str lr, [r0, #56]
- str lr, [r0, #60] @ store return address as pc
-#endif
-#if __ARM_ARCH_ISA_THUMB == 1
- @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
- @ It is safe to use here though because we are about to return, and cpsr is
- @ not expected to be preserved.
- movs r0, #0 @ return UNW_ESUCCESS
-#else
- mov r0, #0 @ return UNW_ESUCCESS
-#endif
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3-d16
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
- vstmia r0, {d0-d15}
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3-d16
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
- vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
- .fpu vfpv3
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
- @ VFP and iwMMX instructions are only available when compiling with the flags
- @ that enable them. We do not want to do that in the library (because we do not
- @ want the compiler to generate instructions that access those) but this is
- @ only accessed if the personality routine needs these registers. Use of
- @ these registers implies they are, actually, available on the target, so
- @ it's ok to execute.
- @ So, generate the instructions using the corresponding coprocessor mnemonic.
- vstmia r0, {d16-d31}
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
- stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
- stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
- stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
- stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
- stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
- stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
- stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
- stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
- stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
- stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
- stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
- stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
- stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
- stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
- stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
- stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
-#endif
- JMP(lr)
-
-@
-@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
-@
-@ On entry:
-@ values pointer is in r0
-@
- .p2align 2
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
- stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
- stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
- stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
- stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
-#endif
- JMP(lr)
-
-#elif defined(__or1k__)
-
-#
-# extern int unw_getcontext(unw_context_t* thread_state)
-#
-# On entry:
-# thread_state pointer is in r3
-#
-DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- l.sw 0(r3), r0
- l.sw 4(r3), r1
- l.sw 8(r3), r2
- l.sw 12(r3), r3
- l.sw 16(r3), r4
- l.sw 20(r3), r5
- l.sw 24(r3), r6
- l.sw 28(r3), r7
- l.sw 32(r3), r8
- l.sw 36(r3), r9
- l.sw 40(r3), r10
- l.sw 44(r3), r11
- l.sw 48(r3), r12
- l.sw 52(r3), r13
- l.sw 56(r3), r14
- l.sw 60(r3), r15
- l.sw 64(r3), r16
- l.sw 68(r3), r17
- l.sw 72(r3), r18
- l.sw 76(r3), r19
- l.sw 80(r3), r20
- l.sw 84(r3), r21
- l.sw 88(r3), r22
- l.sw 92(r3), r23
- l.sw 96(r3), r24
- l.sw 100(r3), r25
- l.sw 104(r3), r26
- l.sw 108(r3), r27
- l.sw 112(r3), r28
- l.sw 116(r3), r29
- l.sw 120(r3), r30
- l.sw 124(r3), r31
-
-#elif defined(__riscv__)
-
-/* RISCVTODO */
-
-#endif
Index: contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp
===================================================================
--- contrib/llvm/projects/libunwind/src/Unwind_AppleExtras.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-//===--------------------- Unwind_AppleExtras.cpp -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "config.h"
-#include "DwarfParser.hpp"
-#include "unwind_ext.h"
-
-
-// private keymgr stuff
-#define KEYMGR_GCC3_DW2_OBJ_LIST 302
-extern "C" {
- extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr);
- extern void *_keymgr_get_and_lock_processwide_ptr(int key);
-}
-
-// undocumented libgcc "struct object"
-struct libgcc_object {
- void *start;
- void *unused1;
- void *unused2;
- void *fde;
- unsigned long encoding;
- void *fde_end;
- libgcc_object *next;
-};
-
-// undocumented libgcc "struct km_object_info" referenced by
-// KEYMGR_GCC3_DW2_OBJ_LIST
-struct libgcc_object_info {
- libgcc_object *seen_objects;
- libgcc_object *unseen_objects;
- unsigned spare[2];
-};
-
-
-// static linker symbols to prevent wrong two level namespace for _Unwind symbols
-#if defined(__arm__)
- #define NOT_HERE_BEFORE_5_0(sym) \
- extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
- extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
- extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
- __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
- extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
- extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
- extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
- extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp43 = 0;
-#elif defined(__arm64__)
- #define NOT_HERE_BEFORE_10_6(sym)
- #define NEVER_HERE(sym)
-#else
- #define NOT_HERE_BEFORE_10_6(sym) \
- extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
- extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp5 = 0;
- #define NEVER_HERE(sym) \
- extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
- extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
- extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
-#endif
-
-
-#if _LIBUNWIND_BUILD_ZERO_COST_APIS
-
-//
-// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
-NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
-NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
-NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume)
-NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
-NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
-NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
-NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_10_6(__register_frame)
-NOT_HERE_BEFORE_10_6(__deregister_frame)
-
-//
-// symbols in libSystem.dylib for compatibility, but we don't want any new code
-// using them
-//
-NEVER_HERE(__register_frame_info_bases)
-NEVER_HERE(__register_frame_info)
-NEVER_HERE(__register_frame_info_table_bases)
-NEVER_HERE(__register_frame_info_table)
-NEVER_HERE(__register_frame_table)
-NEVER_HERE(__deregister_frame_info)
-NEVER_HERE(__deregister_frame_info_bases)
-
-#endif // _LIBUNWIND_BUILD_ZERO_COST_APIS
-
-
-
-
-#if _LIBUNWIND_BUILD_SJLJ_APIS
-//
-// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
-NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
-
-#endif // _LIBUNWIND_BUILD_SJLJ_APIS
-
-
-namespace libunwind {
-
-_LIBUNWIND_HIDDEN
-bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
-#if __MAC_OS_X_VERSION_MIN_REQUIRED
- // lastly check for old style keymgr registration of dynamically generated
- // FDEs acquire exclusive access to libgcc_object_info
- libgcc_object_info *head = (libgcc_object_info *)
- _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
- if (head != NULL) {
- // look at each FDE in keymgr
- for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) {
- CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
- CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
- const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE(
- LocalAddressSpace::sThisAddressSpace,
- (uintptr_t)ob->fde, &fdeInfo, &cieInfo);
- if (msg == NULL) {
- // Check if this FDE is for a function that includes the pc
- if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
- fde = (void*)fdeInfo.pcStart;
- _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
- head);
- return true;
- }
- }
- }
- }
- // release libgcc_object_info
- _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
-#else
- (void)pc;
- (void)fde;
-#endif
- return false;
-}
-
-}
-
-
-#if !defined(FOR_DYLD) && _LIBUNWIND_BUILD_SJLJ_APIS
-
-#include <System/pthread_machdep.h>
-
-// Accessors to get get/set linked list of frames for sjlj based execeptions.
-_LIBUNWIND_HIDDEN
-struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
- return (struct _Unwind_FunctionContext *)
- _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
-}
-
-_LIBUNWIND_HIDDEN
-void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
- _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
-}
-#endif
-
-
-
-
Index: contrib/llvm/projects/libunwind/src/assembly.h
===================================================================
--- contrib/llvm/projects/libunwind/src/assembly.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* ===-- assembly.h - libUnwind assembler support macros -------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===----------------------------------------------------------------------===
- *
- * This file defines macros for use in libUnwind assembler source.
- * This file is not part of the interface of this library.
- *
- * ===----------------------------------------------------------------------===
- */
-
-#ifndef UNWIND_ASSEMBLY_H
-#define UNWIND_ASSEMBLY_H
-
-#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
-#define SEPARATOR @
-#elif defined(__arm64__)
-#define SEPARATOR %%
-#else
-#define SEPARATOR ;
-#endif
-
-#if defined(__APPLE__)
-#define HIDDEN_DIRECTIVE .private_extern
-#else
-#define HIDDEN_DIRECTIVE .hidden
-#endif
-
-#define GLUE2(a, b) a ## b
-#define GLUE(a, b) GLUE2(a, b)
-#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
-
-#if defined(__APPLE__)
-#define SYMBOL_IS_FUNC(name)
-#elif defined(__ELF__)
-#if defined(__arm__)
-#define SYMBOL_IS_FUNC(name) .type name,%function
-#else
-#define SYMBOL_IS_FUNC(name) .type name,@function
-#endif
-#else
-#define SYMBOL_IS_FUNC(name) \
- .def name SEPARATOR \
- .scl 2 SEPARATOR \
- .type 32 SEPARATOR \
- .endef
-#endif
-
-#define DEFINE_LIBUNWIND_FUNCTION(name) \
- .globl SYMBOL_NAME(name) SEPARATOR \
- SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
- SYMBOL_NAME(name):
-
-#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \
- .globl SYMBOL_NAME(name) SEPARATOR \
- HIDDEN_DIRECTIVE SYMBOL_NAME(name) SEPARATOR \
- SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
- SYMBOL_NAME(name):
-
-#if defined(__arm__)
-#if !defined(__ARM_ARCH)
-#define __ARM_ARCH 4
-#endif
-
-#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
-#define ARM_HAS_BX
-#endif
-
-#ifdef ARM_HAS_BX
-#define JMP(r) bx r
-#else
-#define JMP(r) mov pc, r
-#endif
-#endif /* __arm__ */
-
-#endif /* UNWIND_ASSEMBLY_H */
Index: contrib/llvm/projects/libunwind/src/config.h
===================================================================
--- contrib/llvm/projects/libunwind/src/config.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//===----------------------------- 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.
-//
-//===----------------------------------------------------------------------===//
-
-
-#ifndef LIBUNWIND_CONFIG_H
-#define LIBUNWIND_CONFIG_H
-
-#include <assert.h>
-#include <stdio.h>
-
-// 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__
- #include <Availability.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- void __assert_rtn(const char *, const char *, int, const char *)
- __attribute__((noreturn));
- #ifdef __cplusplus
- }
- #endif
-
- #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
- defined(__x86_64__) || \
- defined(__arm64__) || \
- defined(__mips__))
- #define _LIBUNWIND_BUILD_SJLJ_APIS defined(__arm__)
- #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
- defined(__x86_64__))
- #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
- #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
- #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
- #define _LIBUNWIND_ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg)
-
- #if defined(FOR_DYLD)
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
- #else
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
- #endif
-
-#else
- #include <stdlib.h>
-
- static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) __attribute__ ((noreturn));
- static inline void assert_rtn(const char* func, const char* file, int line, const char* msg) {
- fprintf(stderr, "libunwind: %s %s:%d - %s\n", func, file, line, msg);
- assert(false);
- abort();
- }
-
- #define _LIBUNWIND_BUILD_ZERO_COST_APIS (defined(__i386__) || \
- defined(__x86_64__) || \
- defined(__arm__) || \
- defined(__aarch64__) || \
- defined(__riscv__))
- #define _LIBUNWIND_BUILD_SJLJ_APIS 0
- #define _LIBUNWIND_SUPPORT_FRAME_APIS (defined(__i386__) || \
- defined(__x86_64__))
- #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
- #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
- #define _LIBUNWIND_LOG(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
- #define _LIBUNWIND_ABORT(msg) assert_rtn(__func__, __FILE__, __LINE__, msg)
-
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND !defined(__arm__) || \
- defined(__ARM_DWARF_EH__)
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX _LIBUNWIND_SUPPORT_DWARF_UNWIND
-#endif
-
-
-// Macros that define away in non-Debug builds
-#ifdef NDEBUG
- #define _LIBUNWIND_DEBUG_LOG(msg, ...)
- #define _LIBUNWIND_TRACE_API(msg, ...)
- #define _LIBUNWIND_TRACING_UNWINDING 0
- #define _LIBUNWIND_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
-
-
-#endif // LIBUNWIND_CONFIG_H
Index: contrib/llvm/projects/libunwind/src/libunwind.cpp
===================================================================
--- contrib/llvm/projects/libunwind/src/libunwind.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-//===--------------------------- libuwind.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 <libunwind.h>
-//
-//===----------------------------------------------------------------------===//
-
-#include <libunwind.h>
-
-#ifndef NDEBUG
-#include <cstdlib> // getenv
-#endif
-#include <new>
-#include <algorithm>
-
-#include "libunwind_ext.h"
-#include "config.h"
-
-#include <stdlib.h>
-
-
-#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",
- static_cast<void *>(cursor),
- static_cast<void *>(context));
- // Use "placement new" to allocate UnwindCursor in the cursor buffer.
-#if defined(__i386__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__x86_64__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__ppc__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_ppc>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__arm64__) || defined(__aarch64__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif _LIBUNWIND_ARM_EHABI
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__or1k__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_or1k>(
- context, LocalAddressSpace::sThisAddressSpace);
-#elif defined(__mips__)
-#warning The MIPS architecture is not supported.
-#elif defined(__riscv__)
- new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_riscv>(
- context, LocalAddressSpace::sThisAddressSpace);
-#else
-#error Architecture not supported
-#endif
- 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<OtherAddressSpace<Pointer32<LittleEndian> >,
- Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
- break;
- case CPU_TYPE_X86_64:
- new ((void *)cursor) UnwindCursor<
- OtherAddressSpace<Pointer64<LittleEndian> >, Registers_x86_64>(
- ((unw_addr_space_x86_64 *)as)->oas, arg);
- break;
- case CPU_TYPE_POWERPC:
- new ((void *)cursor)
- UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >, Registers_ppc>(
- ((unw_addr_space_ppc *)as)->oas, arg);
- break;
- default:
- return UNW_EUNSPEC;
- }
- return UNW_ESUCCESS;
-}
-
-
-static bool is64bit(task_t task) {
- return false; // FIXME
-}
-
-/// Create an address_space object for use in examining another task.
-_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
-#if __i386__
- if (is64bit(task)) {
- unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
- as->taskPort = task;
- as->cpuType = CPU_TYPE_X86_64;
- //as->oas
- } else {
- unw_addr_space_i386 *as = new unw_addr_space_i386(task);
- as->taskPort = task;
- as->cpuType = CPU_TYPE_I386;
- //as->oas
- }
-#else
-// FIXME
-#endif
-}
-
-
-/// Delete an address_space object.
-_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
- switch (asp->cpuType) {
-#if __i386__ || __x86_64__
- case CPU_TYPE_I386: {
- unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
- delete as;
- }
- break;
- case CPU_TYPE_X86_64: {
- unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
- delete as;
- }
- break;
-#endif
- case CPU_TYPE_POWERPC: {
- unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
- delete as;
- }
- break;
- }
-}
-#endif // UNW_REMOTE
-
-
-/// Get value of specified register at cursor position in stack frame.
-_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
- unw_word_t *value) {
- _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n",
- static_cast<void *>(cursor), regNum,
- static_cast<void *>(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",
- static_cast<void *>(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",
- static_cast<void *>(cursor), regNum,
- static_cast<void *>(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",
- static_cast<void *>(cursor), regNum, value);
-#else
- _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n",
- static_cast<void *>(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<void *>(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",
- static_cast<void *>(cursor), static_cast<void *>(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<void *>(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",
- static_cast<void *>(cursor), static_cast<void *>(buf),
- static_cast<unsigned long>(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",
- static_cast<void *>(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",
- static_cast<void *>(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",
- static_cast<void *>(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",
- static_cast<void *>(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",
- reinterpret_cast<void *>(func));
- DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
-}
-
-
-/// IPI: for __register_frame()
-void _unw_add_dynamic_fde(unw_word_t fde) {
- CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
- CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
- const char *message = CFI_Parser<LocalAddressSpace>::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<LocalAddressSpace>::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<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
-}
-#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
-
-
-
-// Add logging hooks in Debug builds only
-#ifndef NDEBUG
-#include <stdlib.h>
-
-_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: contrib/llvm/projects/libunwind/src/libunwind_ext.h
===================================================================
--- contrib/llvm/projects/libunwind/src/libunwind_ext.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===------------------------ libunwind_ext.h -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Extensions to libunwind API.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __LIBUNWIND_EXT__
-#define __LIBUNWIND_EXT__
-
-#include "config.h"
-#include <libunwind.h>
-#include <unwind.h>
-
-#define UNW_STEP_SUCCESS 1
-#define UNW_STEP_END 0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// SPI
-extern 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));
-
-// IPI
-extern void _unw_add_dynamic_fde(unw_word_t fde);
-extern void _unw_remove_dynamic_fde(unw_word_t fde);
-
-#if _LIBUNWIND_ARM_EHABI
-extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
-extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
- const uint32_t *data,
- size_t offset, size_t len);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __LIBUNWIND_EXT__
Index: contrib/llvm/projects/libunwind/src/unwind_ext.h
===================================================================
--- contrib/llvm/projects/libunwind/src/unwind_ext.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===-------------------------- unwind_ext.h ------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//
-// Extensions to unwind API.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef __UNWIND_EXT__
-#define __UNWIND_EXT__
-
-#include "unwind.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// These platform specific functions to get and set the top context are
-// implemented elsewhere.
-
-extern struct _Unwind_FunctionContext *
-__Unwind_SjLj_GetTopOfFunctionStack();
-
-extern void
-__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __UNWIND_EXT__
-
-
Index: contrib/llvm/tools/clang/lib/Driver/Tools.cpp
===================================================================
--- contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -7916,12 +7916,12 @@
if (IsPIE)
CmdArgs.push_back("-pie");
+ CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
Index: contrib/netbsd-unwind/AddressSpace.hpp
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/AddressSpace.hpp
@@ -0,0 +1,486 @@
+//===------------------------- 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 <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <dlfcn.h>
+#include <elf.h>
+#include <link.h>
+#include <pthread.h>
+
+#include "dwarf2.h"
+#include "rbtree.h"
+
+namespace _Unwind {
+
+static int rangeCmp(void *, const void *, const void *);
+static int rangeCmpKey(void *, const void *, const void *);
+static int dsoTableCmp(void *, const void *, const void *);
+static int dsoTableCmpKey(void *, const void *, const void *);
+static int phdr_callback(struct dl_phdr_info *, size_t, void *);
+
+struct unw_proc_info_t {
+ uintptr_t data_base; // Base address for data-relative relocations
+ uintptr_t start_ip; // Start address of function
+ uintptr_t end_ip; // First address after end of function
+ uintptr_t lsda; // Address of Language Specific Data Area
+ uintptr_t handler; // Personality routine
+ uintptr_t extra_args; // Extra stack space for frameless routines
+ uintptr_t unwind_info; // Address of DWARF unwind info
+};
+
+/// 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 LocalAddressSpace {
+public:
+ typedef uintptr_t pint_t;
+ typedef intptr_t sint_t;
+
+ typedef void (*findPCRange_t)(LocalAddressSpace &, pint_t, pint_t &pcStart,
+ pint_t &pcEnd);
+
+ LocalAddressSpace(findPCRange_t findPCRange_)
+ : findPCRange(findPCRange_), needsReload(true) {
+ static const rb_tree_ops_t segmentTreeOps = {
+ rangeCmp, rangeCmpKey, offsetof(Range, range_link), NULL
+ };
+ static const rb_tree_ops_t dsoTreeOps = {
+ dsoTableCmp, dsoTableCmpKey, offsetof(Range, dso_link), NULL
+ };
+ __rb_tree_init(&segmentTree, &segmentTreeOps);
+ __rb_tree_init(&dsoTree, &dsoTreeOps);
+ pthread_rwlock_init(&fdeTreeLock, NULL);
+ }
+
+ 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;
+ }
+
+ uintptr_t getP(pint_t addr) {
+ if (sizeof(uintptr_t) == sizeof(uint32_t))
+ return get32(addr);
+ else
+ return get64(addr);
+ }
+
+ uint64_t getULEB128(pint_t &addr, pint_t end) {
+ uint64_t result = 0;
+ uint8_t byte;
+ int bit = 0;
+ do {
+ uint64_t b;
+
+ assert(addr != end);
+
+ byte = get8(addr++);
+ b = byte & 0x7f;
+
+ assert(bit < 64);
+ assert(b << bit >> bit == b);
+
+ result |= b << bit;
+ bit += 7;
+ } while (byte >= 0x80);
+ return result;
+ }
+
+ int64_t getSLEB128(pint_t &addr, pint_t end) {
+ uint64_t result = 0;
+ uint8_t byte;
+ int bit = 0;
+ do {
+ uint64_t b;
+
+ assert(addr != end);
+
+ byte = get8(addr++);
+ b = byte & 0x7f;
+
+ assert(bit < 64);
+ assert(b << bit >> bit == b);
+
+ result |= b << bit;
+ bit += 7;
+ } while (byte >= 0x80);
+ // sign extend negative numbers
+ if ((byte & 0x40) != 0)
+ result |= (-1LL) << bit;
+ return result;
+ }
+
+ pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
+ const unw_proc_info_t *ctx) {
+ pint_t startAddr = addr;
+ const uint8_t *p = (uint8_t *)addr;
+ pint_t result;
+
+ if (encoding == DW_EH_PE_omit)
+ return 0;
+ if (encoding == DW_EH_PE_aligned) {
+ addr = (addr + sizeof(pint_t) - 1) & sizeof(pint_t);
+ return getP(addr);
+ }
+
+ // 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 = 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 = get64(addr);
+ p += 8;
+ addr = (pint_t)p;
+ break;
+ case DW_EH_PE_sleb128:
+ result = getSLEB128(addr, end);
+ break;
+ case DW_EH_PE_sdata2:
+ result = (int16_t)get16(addr);
+ p += 2;
+ addr = (pint_t)p;
+ break;
+ case DW_EH_PE_sdata4:
+ result = (int32_t)get32(addr);
+ p += 4;
+ addr = (pint_t)p;
+ break;
+ case DW_EH_PE_sdata8:
+ result = get64(addr);
+ p += 8;
+ addr = (pint_t)p;
+ break;
+ case DW_EH_PE_omit:
+ result = 0;
+ break;
+ default:
+ assert(0 && "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:
+ assert(0 && "DW_EH_PE_textrel pointer encoding not supported");
+ break;
+ case DW_EH_PE_datarel:
+ assert(ctx != NULL && "DW_EH_PE_datarel without context");
+ if (ctx)
+ result += ctx->data_base;
+ break;
+ case DW_EH_PE_funcrel:
+ assert(ctx != NULL && "DW_EH_PE_funcrel without context");
+ if (ctx)
+ result += ctx->start_ip;
+ break;
+ case DW_EH_PE_aligned:
+ __builtin_unreachable();
+ default:
+ assert(0 && "unknown pointer encoding");
+ break;
+ }
+
+ if (encoding & DW_EH_PE_indirect)
+ result = getP(result);
+
+ return result;
+ }
+
+ bool findFDE(pint_t pc, pint_t &fdeStart, pint_t &data_base) {
+ Range *n;
+ for (;;) {
+ pthread_rwlock_rdlock(&fdeTreeLock);
+ n = (Range *)__rb_tree_find_node(&segmentTree, &pc);
+ pthread_rwlock_unlock(&fdeTreeLock);
+ if (n != NULL)
+ break;
+ if (!needsReload)
+ break;
+ lazyReload();
+ }
+ if (n == NULL)
+ return false;
+ if (n->hdr_start == 0) {
+ fdeStart = n->hdr_base;
+ data_base = n->data_base;
+ return true;
+ }
+
+ pint_t base = n->hdr_base;
+ pint_t first = n->hdr_start;
+ for (pint_t len = n->hdr_entries; len > 1; ) {
+ pint_t next = first + (len / 2) * 8;
+ pint_t nextPC = base + (int32_t)get32(next);
+ if (nextPC == pc) {
+ first = next;
+ break;
+ }
+ if (nextPC < pc) {
+ first = next;
+ len -= (len / 2);
+ } else {
+ len /= 2;
+ }
+ }
+ fdeStart = base + (int32_t)get32(first + 4);
+ data_base = n->data_base;
+ return true;
+ }
+
+ bool addFDE(pint_t pcStart, pint_t pcEnd, pint_t fde) {
+ pthread_rwlock_wrlock(&fdeTreeLock);
+ Range *n = (Range *)malloc(sizeof(*n));
+ n->hdr_base = fde;
+ n->hdr_start = 0;
+ n->hdr_entries = 0;
+ n->first_pc = pcStart;
+ n->last_pc = pcEnd;
+ n->data_base = 0;
+ n->ehframe_base = 0;
+ if (static_cast<Range *>(__rb_tree_insert_node(&segmentTree, n)) == n) {
+ pthread_rwlock_unlock(&fdeTreeLock);
+ return true;
+ }
+ free(n);
+ pthread_rwlock_unlock(&fdeTreeLock);
+ return false;
+ }
+
+ bool removeFDE(pint_t pcStart, pint_t pcEnd, pint_t fde) {
+ pthread_rwlock_wrlock(&fdeTreeLock);
+ Range *n = static_cast<Range *>(__rb_tree_find_node(&segmentTree, &pcStart));
+ if (n == NULL) {
+ pthread_rwlock_unlock(&fdeTreeLock);
+ return false;
+ }
+ assert(n->first_pc == pcStart);
+ assert(n->last_pc == pcEnd);
+ assert(n->hdr_base == fde);
+ assert(n->hdr_start == 0);
+ assert(n->hdr_entries == 0);
+ assert(n->data_base == 0);
+ assert(n->ehframe_base == 0);
+ __rb_tree_remove_node(&segmentTree, n);
+ free(n);
+ pthread_rwlock_unlock(&fdeTreeLock);
+ return true;
+ }
+
+ void removeDSO(pint_t ehFrameBase) {
+ pthread_rwlock_wrlock(&fdeTreeLock);
+ Range *n;
+ n = (Range *)__rb_tree_find_node(&dsoTree, &ehFrameBase);
+ if (n == NULL) {
+ pthread_rwlock_unlock(&fdeTreeLock);
+ return;
+ }
+ __rb_tree_remove_node(&dsoTree, n);
+ __rb_tree_remove_node(&segmentTree, n);
+ free(n);
+ pthread_rwlock_unlock(&fdeTreeLock);
+ }
+
+ void setLazyReload() {
+ pthread_rwlock_wrlock(&fdeTreeLock);
+ needsReload = true;
+ pthread_rwlock_unlock(&fdeTreeLock);
+ }
+
+private:
+ findPCRange_t findPCRange;
+ bool needsReload;
+ pthread_rwlock_t fdeTreeLock;
+ rb_tree_t segmentTree;
+ rb_tree_t dsoTree;
+
+ friend int phdr_callback(struct dl_phdr_info *, size_t, void *);
+ friend int rangeCmp(void *, const void *, const void *);
+ friend int rangeCmpKey(void *, const void *, const void *);
+ friend int dsoTableCmp(void *, const void *, const void *);
+ friend int dsoTableCmpKey(void *, const void *, const void *);
+
+ void updateRange();
+
+ struct Range {
+ rb_node_t range_link;
+ rb_node_t dso_link;
+ pint_t hdr_base; // Pointer to FDE if hdr_start == 0
+ pint_t hdr_start;
+ pint_t hdr_entries;
+ pint_t first_pc;
+ pint_t last_pc;
+ pint_t data_base;
+ pint_t ehframe_base;
+ };
+
+ void lazyReload() {
+ pthread_rwlock_wrlock(&fdeTreeLock);
+ dl_iterate_phdr(phdr_callback, this);
+ needsReload = false;
+ pthread_rwlock_unlock(&fdeTreeLock);
+ }
+
+ void addDSO(pint_t header, pint_t data_base) {
+ if (header == 0)
+ return;
+ if (get8(header) != 1)
+ return;
+ if (get8(header + 3) != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+ return;
+ pint_t end = header + 4;
+ pint_t ehframe_base = getEncodedP(end, 0, get8(header + 1), NULL);
+ pint_t entries = getEncodedP(end, 0, get8(header + 2), NULL);
+ pint_t start = (end + 3) & ~pint_t(3);
+ if (entries == 0)
+ return;
+ Range *n = (Range *)malloc(sizeof(*n));
+ n->hdr_base = header;
+ n->hdr_start = start;
+ n->hdr_entries = entries;
+ n->first_pc = header + (int32_t)get32(n->hdr_start);
+ pint_t tmp;
+ (*findPCRange)(
+ *this, header + (int32_t)get32(n->hdr_start + (entries - 1) * 8 + 4),
+ tmp, n->last_pc);
+ n->data_base = data_base;
+ n->ehframe_base = ehframe_base;
+
+ if (static_cast<Range *>(__rb_tree_insert_node(&segmentTree, n)) != n) {
+ free(n);
+ return;
+ }
+ __rb_tree_insert_node(&dsoTree, n);
+ }
+};
+
+static int phdr_callback(struct dl_phdr_info *info, size_t size, void *data_) {
+ LocalAddressSpace *data = (LocalAddressSpace *)data_;
+ size_t eh_frame = 0, data_base = 0;
+ const Elf_Phdr *hdr = info->dlpi_phdr;
+ const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum;
+ const Elf_Dyn *dyn;
+
+ for (; hdr != last_hdr; ++hdr) {
+ switch (hdr->p_type) {
+ case PT_GNU_EH_FRAME:
+ eh_frame = info->dlpi_addr + hdr->p_vaddr;
+ break;
+ case PT_DYNAMIC:
+ dyn = (const Elf_Dyn *)(info->dlpi_addr + hdr->p_vaddr);
+ while (dyn->d_tag != DT_NULL) {
+ if (dyn->d_tag == DT_PLTGOT) {
+ data_base = info->dlpi_addr + dyn->d_un.d_ptr;
+ break;
+ }
+ ++dyn;
+ }
+ }
+ }
+
+ if (eh_frame)
+ data->addDSO(eh_frame, data_base);
+
+ return 0;
+}
+
+static int rangeCmp(void *context, const void *n1_, const void *n2_) {
+ const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
+ const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
+
+ if (n1->first_pc < n2->first_pc)
+ return -1;
+ if (n1->first_pc > n2->first_pc)
+ return 1;
+ assert(n1->last_pc == n2->last_pc);
+ return 0;
+}
+
+static int rangeCmpKey(void *context, const void *n_, const void *pc_) {
+ const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
+ const LocalAddressSpace::pint_t *pc = (const LocalAddressSpace::pint_t *)pc_;
+ if (n->last_pc < *pc)
+ return -1;
+ if (n->first_pc > *pc)
+ return 1;
+ return 0;
+}
+
+static int dsoTableCmp(void *context, const void *n1_, const void *n2_) {
+ const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
+ const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
+
+ if (n1->ehframe_base < n2->ehframe_base)
+ return -1;
+ if (n1->ehframe_base > n2->ehframe_base)
+ return 1;
+ return 0;
+}
+
+static int dsoTableCmpKey(void *context, const void *n_, const void *ptr_) {
+ const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
+ const LocalAddressSpace::pint_t *ptr = (const LocalAddressSpace::pint_t *)ptr_;
+ if (n->ehframe_base < *ptr)
+ return -1;
+ if (n->ehframe_base > *ptr)
+ return 1;
+ return 0;
+}
+
+} // namespace _Unwind
+
+#endif // __ADDRESSSPACE_HPP__
Index: contrib/netbsd-unwind/CREDITS.TXT
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/CREDITS.TXT
@@ -0,0 +1,42 @@
+This file is a partial list of people who have contributed to the LLVM/libc++abi
+project. If you have contributed a patch or made some other contribution to
+LLVM/libc++abi, please submit a patch to this file to add yourself, and it will be
+done!
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S).
+
+N: Marshall Clow
+E: mclow.lists@gmail.com
+E: marshall@idio.com
+D: Architect and primary coauthor of libc++abi
+
+N: Matthew Dempsky
+E: matthew@dempsky.org
+D: Minor patches and bug fixes.
+
+N: Nowar Gu
+E: wenhan.gu@gmail.com
+D: Minor patches and fixes
+
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary coauthor of libc++abi
+
+N: Nick Kledzik
+E: kledzik@apple.com
+
+N: Bruce Mitchener, Jr.
+E: bruce.mitchener@gmail.com
+D: Minor typo fixes
+
+N: Andrew Morrow
+E: andrew.c.morrow@gmail.com
+D: Minor patches and fixes
+
+N: Erik Olofsson
+E: erik.olofsson@hansoft.se
+E: erik@olofsson.info
+D: Minor patches and fixes
Index: contrib/netbsd-unwind/DwarfInstructions.hpp
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/DwarfInstructions.hpp
@@ -0,0 +1,591 @@
+//===-------------------------- DwarfInstructions.hpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//
+// Processor specific interpretation of DWARF unwind info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __DWARF_INSTRUCTIONS_HPP__
+#define __DWARF_INSTRUCTIONS_HPP__
+
+#include <cstdint>
+#include <cstdlib>
+
+#include "dwarf2.h"
+#include "AddressSpace.hpp"
+#include "Registers.hpp"
+#include "DwarfParser.hpp"
+
+namespace _Unwind {
+
+enum step_result {
+ UNW_STEP_SUCCESS,
+ UNW_STEP_END,
+ UNW_STEP_FAILED
+};
+
+/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
+/// architecture
+template <typename A, typename R> class DwarfInstructions {
+public:
+ typedef typename A::pint_t pint_t;
+ typedef typename A::sint_t sint_t;
+
+ static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
+
+private:
+ static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
+ static pint_t
+ getSavedRegister(A &, const R &, pint_t,
+ const typename CFI_Parser<A, R>::RegisterLocation &);
+ static pint_t
+ computeRegisterLocation(A &, const R &, pint_t,
+ const typename CFI_Parser<A, R>::RegisterLocation &);
+
+ static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
+
+ static pint_t getCFA(A &addressSpace,
+ const typename CFI_Parser<A, R>::PrologInfo &prolog,
+ const R &registers) {
+ if (prolog.cfaRegister != 0)
+ return registers.getRegister(prolog.cfaRegister) +
+ prolog.cfaRegisterOffset;
+ if (prolog.cfaExpression != 0)
+ return evaluateExpression(prolog.cfaExpression, addressSpace, registers,
+ 0);
+ assert(0 && "getCFA(): unknown location");
+ __builtin_unreachable();
+ }
+};
+
+template <typename A, typename R>
+typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
+ A &addressSpace, const R &registers, pint_t cfa,
+ const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
+ switch (savedReg.location) {
+ case CFI_Parser<A, R>::kRegisterInCFA:
+ return addressSpace.getP(cfa + savedReg.value);
+
+ case CFI_Parser<A, R>::kRegisterAtExpression:
+ return addressSpace.getP(
+ evaluateExpression(savedReg.value, addressSpace, registers, cfa));
+
+ case CFI_Parser<A, R>::kRegisterIsExpression:
+ return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
+
+ case CFI_Parser<A, R>::kRegisterInRegister:
+ return registers.getRegister(savedReg.value);
+
+ case CFI_Parser<A, R>::kRegisterUnused:
+ case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
+ assert(0 && "unsupported restore location for register");
+ }
+ __builtin_unreachable();
+}
+
+template <typename A, typename R>
+typename DwarfInstructions<A, R>::pint_t
+DwarfInstructions<A, R>::computeRegisterLocation(
+ A &addressSpace, const R &registers, pint_t cfa,
+ const typename CFI_Parser<A, R>::RegisterLocation &savedReg) {
+ switch (savedReg.location) {
+ case CFI_Parser<A, R>::kRegisterInCFA:
+ return cfa + savedReg.value;
+
+ case CFI_Parser<A, R>::kRegisterAtExpression:
+ return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
+
+ case CFI_Parser<A, R>::kRegisterIsExpression:
+ case CFI_Parser<A, R>::kRegisterUnused:
+ case CFI_Parser<A, R>::kRegisterOffsetFromCFA:
+ case CFI_Parser<A, R>::kRegisterInRegister:
+ assert(0 && "unsupported restore location for float/vector register");
+ }
+ __builtin_unreachable();
+}
+
+template <typename A, typename R>
+step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
+ pint_t fdeStart,
+ R &registers,
+ unw_proc_info_t *ctx) {
+ typename CFI_Parser<A, R>::FDE_Info fdeInfo;
+ typename CFI_Parser<A, R>::CIE_Info cieInfo;
+ if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo,
+ ctx))
+ return UNW_STEP_FAILED;
+
+ typename CFI_Parser<A, R>::PrologInfo prolog;
+ if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo,
+ pc, &prolog, ctx))
+ return UNW_STEP_FAILED;
+
+ // Create working copy of the register set.
+ R newRegisters = registers;
+
+ // Get pointer to CFA by the architecture-specific code.
+ pint_t cfa = getCFA(addressSpace, prolog, registers);
+
+ // Restore registers according to DWARF instructions
+ pint_t returnAddress = 0;
+ for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
+ if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
+ continue;
+ if (i == (int)cieInfo.returnAddressRegister)
+ returnAddress = getSavedRegister(addressSpace, registers, cfa,
+ prolog.savedRegisters[i]);
+ else if (registers.validRegister(i))
+ newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa,
+ prolog.savedRegisters[i]));
+ else if (registers.validFloatVectorRegister(i))
+ newRegisters.copyFloatVectorRegister(
+ i, computeRegisterLocation(addressSpace, registers, cfa,
+ prolog.savedRegisters[i]));
+ else
+ return UNW_STEP_FAILED;
+ }
+
+ // The CFA is defined as the stack pointer at the call site.
+ // Therefore the SP is restored by setting it to the CFA.
+ newRegisters.setSP(cfa);
+ newRegisters.setIP(returnAddress + R::RETURN_OFFSET);
+ returnAddress += R::RETURN_OFFSET;
+ returnAddress &= ~R::RETURN_MASK;
+ newRegisters.setIP(returnAddress);
+
+ // Now replace register set with the working copy.
+ registers = newRegisters;
+
+ return UNW_STEP_SUCCESS;
+}
+
+template <typename A, typename R>
+typename A::pint_t
+DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
+ const R &registers,
+ pint_t initialStackValue) {
+ pint_t p = expression;
+ pint_t expressionEnd = expression + 20; // Rough estimate
+ uint64_t length = addressSpace.getULEB128(p, expressionEnd);
+ expressionEnd = p + length;
+ pint_t stack[100];
+ pint_t *sp = stack;
+ *(++sp) = initialStackValue;
+
+ while (p < expressionEnd) {
+ uint8_t opcode = addressSpace.get8(p++);
+ sint_t svalue;
+ pint_t value;
+ uint32_t reg;
+ switch (opcode) {
+ case DW_OP_addr:
+ // push immediate address sized value
+ value = addressSpace.getP(p);
+ p += sizeof(pint_t);
+ *(++sp) = value;
+ break;
+
+ case DW_OP_deref:
+ // pop stack, dereference, push result
+ value = *sp--;
+ *(++sp) = addressSpace.getP(value);
+ break;
+
+ case DW_OP_const1u:
+ // push immediate 1 byte value
+ value = addressSpace.get8(p);
+ p += 1;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_const1s:
+ // push immediate 1 byte signed value
+ svalue = (int8_t)addressSpace.get8(p);
+ p += 1;
+ *(++sp) = svalue;
+ break;
+
+ case DW_OP_const2u:
+ // push immediate 2 byte value
+ value = addressSpace.get16(p);
+ p += 2;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_const2s:
+ // push immediate 2 byte signed value
+ svalue = (int16_t)addressSpace.get16(p);
+ p += 2;
+ *(++sp) = svalue;
+ break;
+
+ case DW_OP_const4u:
+ // push immediate 4 byte value
+ value = addressSpace.get32(p);
+ p += 4;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_const4s:
+ // push immediate 4 byte signed value
+ svalue = (int32_t)addressSpace.get32(p);
+ p += 4;
+ *(++sp) = svalue;
+ break;
+
+ case DW_OP_const8u:
+ // push immediate 8 byte value
+ value = addressSpace.get64(p);
+ p += 8;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_const8s:
+ // push immediate 8 byte signed value
+ value = (int32_t)addressSpace.get64(p);
+ p += 8;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_constu:
+ // push immediate ULEB128 value
+ value = addressSpace.getULEB128(p, expressionEnd);
+ *(++sp) = value;
+ break;
+
+ case DW_OP_consts:
+ // push immediate SLEB128 value
+ svalue = addressSpace.getSLEB128(p, expressionEnd);
+ *(++sp) = svalue;
+ break;
+
+ case DW_OP_dup:
+ // push top of stack
+ value = *sp;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_drop:
+ // pop
+ --sp;
+ break;
+
+ case DW_OP_over:
+ // dup second
+ value = sp[-1];
+ *(++sp) = value;
+ break;
+
+ case DW_OP_pick:
+ // pick from
+ reg = addressSpace.get8(p);
+ p += 1;
+ value = sp[-reg];
+ *(++sp) = value;
+ break;
+
+ case DW_OP_swap:
+ // swap top two
+ value = sp[0];
+ sp[0] = sp[-1];
+ sp[-1] = value;
+ break;
+
+ case DW_OP_rot:
+ // rotate top three
+ value = sp[0];
+ sp[0] = sp[-1];
+ sp[-1] = sp[-2];
+ sp[-2] = value;
+ break;
+
+ case DW_OP_xderef:
+ // pop stack, dereference, push result
+ value = *sp--;
+ *sp = *((uint64_t *)value);
+ break;
+
+ case DW_OP_abs:
+ svalue = *sp;
+ if (svalue < 0)
+ *sp = -svalue;
+ break;
+
+ case DW_OP_and:
+ value = *sp--;
+ *sp &= value;
+ break;
+
+ case DW_OP_div:
+ svalue = *sp--;
+ *sp = *sp / svalue;
+ break;
+
+ case DW_OP_minus:
+ svalue = *sp--;
+ *sp = *sp - svalue;
+ break;
+
+ case DW_OP_mod:
+ svalue = *sp--;
+ *sp = *sp % svalue;
+ break;
+
+ case DW_OP_mul:
+ svalue = *sp--;
+ *sp = *sp * svalue;
+ break;
+
+ case DW_OP_neg:
+ *sp = 0 - *sp;
+ break;
+
+ case DW_OP_not:
+ svalue = *sp;
+ *sp = ~svalue;
+ break;
+
+ case DW_OP_or:
+ value = *sp--;
+ *sp |= value;
+ break;
+
+ case DW_OP_plus:
+ value = *sp--;
+ *sp += value;
+ break;
+
+ case DW_OP_plus_uconst:
+ // pop stack, add uelb128 constant, push result
+ *sp += addressSpace.getULEB128(p, expressionEnd);
+ break;
+
+ case DW_OP_shl:
+ value = *sp--;
+ *sp = *sp << value;
+ break;
+
+ case DW_OP_shr:
+ value = *sp--;
+ *sp = *sp >> value;
+ break;
+
+ case DW_OP_shra:
+ value = *sp--;
+ svalue = *sp;
+ *sp = svalue >> value;
+ break;
+
+ case DW_OP_xor:
+ value = *sp--;
+ *sp ^= value;
+ break;
+
+ case DW_OP_skip:
+ svalue = (int16_t)addressSpace.get16(p);
+ p += 2;
+ p += svalue;
+ break;
+
+ case DW_OP_bra:
+ svalue = (int16_t)addressSpace.get16(p);
+ p += 2;
+ if (*sp--)
+ p += svalue;
+ break;
+
+ case DW_OP_eq:
+ value = *sp--;
+ *sp = (*sp == value);
+ break;
+
+ case DW_OP_ge:
+ value = *sp--;
+ *sp = (*sp >= value);
+ break;
+
+ case DW_OP_gt:
+ value = *sp--;
+ *sp = (*sp > value);
+ break;
+
+ case DW_OP_le:
+ value = *sp--;
+ *sp = (*sp <= value);
+ break;
+
+ case DW_OP_lt:
+ value = *sp--;
+ *sp = (*sp < value);
+ break;
+
+ case DW_OP_ne:
+ value = *sp--;
+ *sp = (*sp != value);
+ break;
+
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ value = opcode - DW_OP_lit0;
+ *(++sp) = value;
+ break;
+
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ reg = opcode - DW_OP_reg0;
+ *(++sp) = registers.getRegister(reg);
+ break;
+
+ case DW_OP_regx:
+ reg = addressSpace.getULEB128(p, expressionEnd);
+ *(++sp) = registers.getRegister(reg);
+ break;
+
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ reg = opcode - DW_OP_breg0;
+ svalue = addressSpace.getSLEB128(p, expressionEnd);
+ *(++sp) = registers.getRegister(reg) + svalue;
+ break;
+
+ case DW_OP_bregx:
+ reg = addressSpace.getULEB128(p, expressionEnd);
+ svalue = addressSpace.getSLEB128(p, expressionEnd);
+ *(++sp) = registers.getRegister(reg) + svalue;
+ break;
+
+ case DW_OP_deref_size:
+ // pop stack, dereference, push result
+ value = *sp--;
+ switch (addressSpace.get8(p++)) {
+ case 1:
+ value = addressSpace.get8(value);
+ break;
+ case 2:
+ value = addressSpace.get16(value);
+ break;
+ case 4:
+ value = addressSpace.get32(value);
+ break;
+ case 8:
+ value = addressSpace.get64(value);
+ break;
+ default:
+ assert(0 && "DW_OP_deref_size with bad size");
+ }
+ *(++sp) = value;
+ break;
+
+ case DW_OP_fbreg:
+ case DW_OP_piece:
+ case DW_OP_xderef_size:
+ case DW_OP_nop:
+ case DW_OP_push_object_addres:
+ case DW_OP_call2:
+ case DW_OP_call4:
+ case DW_OP_call_ref:
+ default:
+ assert(0 && "dwarf opcode not implemented");
+ }
+ }
+ return *sp;
+}
+
+} // namespace _Unwind
+
+#endif // __DWARF_INSTRUCTIONS_HPP__
Index: contrib/netbsd-unwind/DwarfParser.hpp
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/DwarfParser.hpp
@@ -0,0 +1,546 @@
+//===--------------------------- DwarfParser.hpp --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//
+// Parses DWARF CFIs (FDEs and CIEs).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __DWARF_PARSER_HPP__
+#define __DWARF_PARSER_HPP__
+
+#include <cstdint>
+#include <cstdlib>
+
+#include "dwarf2.h"
+#include "AddressSpace.hpp"
+
+namespace _Unwind {
+
+/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
+/// See Dwarf Spec for details:
+/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
+///
+template <typename A, typename R> class CFI_Parser {
+public:
+ typedef typename A::pint_t pint_t;
+
+ /// Information encoded in a CIE (Common Information Entry)
+ struct CIE_Info {
+ pint_t cieStart;
+ pint_t cieLength;
+ pint_t cieInstructions;
+ pint_t personality;
+ uint32_t codeAlignFactor;
+ int dataAlignFactor;
+ uint8_t pointerEncoding;
+ uint8_t lsdaEncoding;
+ uint8_t personalityEncoding;
+ uint8_t personalityOffsetInCIE;
+ bool isSignalFrame;
+ bool fdesHaveAugmentationData;
+ uint8_t returnAddressRegister;
+ };
+
+ /// Information about an FDE (Frame Description Entry)
+ struct FDE_Info {
+ pint_t fdeStart;
+ pint_t fdeLength;
+ pint_t fdeInstructions;
+ pint_t pcStart;
+ pint_t pcEnd;
+ pint_t lsda;
+ };
+
+ /// Information about a frame layout and registers saved determined
+ /// by "running" the DWARF FDE "instructions"
+ enum {
+ kMaxRegisterNumber = R::LAST_REGISTER + 1
+ };
+ enum RegisterSavedWhere {
+ kRegisterUnused,
+ kRegisterInCFA,
+ kRegisterOffsetFromCFA,
+ kRegisterInRegister,
+ kRegisterAtExpression,
+ kRegisterIsExpression,
+ };
+ struct RegisterLocation {
+ RegisterSavedWhere location;
+ int64_t value;
+ };
+ struct PrologInfo {
+ uint32_t cfaRegister;
+ int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
+ int64_t cfaExpression; // CFA = expression
+ uint32_t spExtraArgSize;
+ uint32_t codeOffsetAtStackDecrement;
+ RegisterLocation savedRegisters[kMaxRegisterNumber];
+ };
+
+ struct PrologInfoStackEntry {
+ PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
+ : next(n), info(i) {}
+ PrologInfoStackEntry *next;
+ PrologInfo info;
+ };
+
+ static void findPCRange(A &, pint_t, pint_t &, pint_t &);
+
+ static bool decodeFDE(A &, pint_t, FDE_Info *, CIE_Info *,
+ unw_proc_info_t *ctx);
+ static bool parseFDEInstructions(A &, const FDE_Info &, const CIE_Info &,
+ pint_t, PrologInfo *, unw_proc_info_t *ctx);
+
+ static bool parseCIE(A &, pint_t, CIE_Info *);
+
+private:
+ static bool parseInstructions(A &, pint_t, pint_t, const CIE_Info &, pint_t,
+ PrologInfoStackEntry *&, PrologInfo *,
+ unw_proc_info_t *ctx);
+};
+
+///
+/// Parse a FDE and return the last PC it covers.
+///
+template <typename A, typename R>
+void CFI_Parser<A, R>::findPCRange(A &addressSpace, pint_t fde, pint_t &pcStart,
+ pint_t &pcEnd) {
+ pcStart = 0;
+ pcEnd = 0;
+ pint_t p = fde;
+ uint64_t cfiLength = addressSpace.get32(p);
+ p += 4;
+ if (cfiLength == 0xffffffff) {
+ // 0xffffffff means length is really the next 8 Bytes.
+ cfiLength = addressSpace.get64(p);
+ p += 8;
+ }
+ if (cfiLength == 0)
+ return;
+ uint32_t ciePointer = addressSpace.get32(p);
+ if (ciePointer == 0)
+ return;
+ pint_t nextCFI = p + cfiLength;
+ pint_t cieStart = p - ciePointer;
+ typename CFI_Parser<A, R>::CIE_Info cieInfo;
+ if (!parseCIE(addressSpace, cieStart, &cieInfo))
+ return;
+ p += 4;
+ // Parse pc begin and range.
+ pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding, NULL);
+ pcEnd = pcStart + addressSpace.getEncodedP(
+ p, nextCFI, cieInfo.pointerEncoding & 0x0F, NULL);
+}
+
+///
+/// Parse a FDE into a CIE_Info and an FDE_Info
+///
+template <typename A, typename R>
+bool CFI_Parser<A, R>::decodeFDE(A &addressSpace, pint_t fdeStart,
+ FDE_Info *fdeInfo, CIE_Info *cieInfo,
+ unw_proc_info_t *ctx) {
+ pint_t p = fdeStart;
+ uint64_t cfiLength = addressSpace.get32(p);
+ p += 4;
+ if (cfiLength == 0xffffffff) {
+ // 0xffffffff means length is really the next 8 Bytes.
+ cfiLength = addressSpace.get64(p);
+ p += 8;
+ }
+ if (cfiLength == 0)
+ return false;
+ uint32_t ciePointer = addressSpace.get32(p);
+ if (ciePointer == 0)
+ return false;
+ pint_t nextCFI = p + cfiLength;
+ pint_t cieStart = p - ciePointer;
+ if (!parseCIE(addressSpace, cieStart, cieInfo))
+ return false;
+ p += 4;
+ // Parse pc begin and range.
+ pint_t pcStart =
+ addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding, ctx);
+ pint_t pcRange = addressSpace.getEncodedP(
+ p, nextCFI, cieInfo->pointerEncoding & 0x0F, ctx);
+ // Parse rest of info.
+ fdeInfo->lsda = 0;
+ // Check for augmentation length
+ if (cieInfo->fdesHaveAugmentationData) {
+ uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
+ pint_t endOfAug = p + augLen;
+ if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
+ // Peek at value (without indirection). Zero means no LSDA.
+ pint_t lsdaStart = p;
+ if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F,
+ ctx) != 0) {
+ // Reset pointer and re-parse LSDA address.
+ p = lsdaStart;
+ fdeInfo->lsda =
+ addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding, ctx);
+ }
+ }
+ p = endOfAug;
+ }
+ fdeInfo->fdeStart = fdeStart;
+ fdeInfo->fdeLength = nextCFI - fdeStart;
+ fdeInfo->fdeInstructions = p;
+ fdeInfo->pcStart = pcStart;
+ fdeInfo->pcEnd = pcStart + pcRange;
+ return true;
+}
+
+/// Extract info from a CIE
+template <typename A, typename R>
+bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
+ CIE_Info *cieInfo) {
+ cieInfo->pointerEncoding = 0;
+ cieInfo->lsdaEncoding = DW_EH_PE_omit;
+ cieInfo->personalityEncoding = 0;
+ cieInfo->personalityOffsetInCIE = 0;
+ cieInfo->personality = 0;
+ cieInfo->codeAlignFactor = 0;
+ cieInfo->dataAlignFactor = 0;
+ cieInfo->isSignalFrame = false;
+ cieInfo->fdesHaveAugmentationData = false;
+ cieInfo->cieStart = cie;
+ pint_t p = cie;
+ uint64_t cieLength = addressSpace.get32(p);
+ p += 4;
+ pint_t cieContentEnd = p + cieLength;
+ if (cieLength == 0xffffffff) {
+ // 0xffffffff means length is really the next 8 Bytes.
+ cieLength = addressSpace.get64(p);
+ p += 8;
+ cieContentEnd = p + cieLength;
+ }
+ if (cieLength == 0)
+ return true;
+ // CIE ID is always 0
+ if (addressSpace.get32(p) != 0)
+ return false;
+ p += 4;
+ // Version is always 1 or 3
+ uint8_t version = addressSpace.get8(p);
+ if (version != 1 && version != 3)
+ return false;
+ ++p;
+ // Save start of augmentation string and find end.
+ pint_t strStart = p;
+ while (addressSpace.get8(p) != 0)
+ ++p;
+ ++p;
+ // Parse code aligment factor
+ cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
+ // Parse data alignment factor
+ cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
+ // Parse return address register
+ cieInfo->returnAddressRegister = (uint8_t)addressSpace.getULEB128(p, cieContentEnd);
+ // Parse augmentation data based on augmentation string.
+ if (addressSpace.get8(strStart) == 'z') {
+ // parse augmentation data length
+ addressSpace.getULEB128(p, cieContentEnd);
+ for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
+ switch (addressSpace.get8(s)) {
+ case 'z':
+ cieInfo->fdesHaveAugmentationData = true;
+ break;
+ case 'P':
+ cieInfo->personalityEncoding = addressSpace.get8(p);
+ ++p;
+ cieInfo->personalityOffsetInCIE = p - cie;
+ cieInfo->personality = addressSpace.getEncodedP(
+ p, cieContentEnd, cieInfo->personalityEncoding, NULL);
+ break;
+ case 'L':
+ cieInfo->lsdaEncoding = addressSpace.get8(p);
+ ++p;
+ break;
+ case 'R':
+ cieInfo->pointerEncoding = addressSpace.get8(p);
+ ++p;
+ break;
+ case 'S':
+ cieInfo->isSignalFrame = true;
+ break;
+ default:
+ // ignore unknown letters
+ break;
+ }
+ }
+ }
+ cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
+ cieInfo->cieInstructions = p;
+ return true;
+}
+
+/// "Run" the dwarf instructions and create the abstact PrologInfo for an FDE.
+template <typename A, typename R>
+bool CFI_Parser<A, R>::parseFDEInstructions(A &addressSpace,
+ const FDE_Info &fdeInfo,
+ const CIE_Info &cieInfo,
+ pint_t upToPC, PrologInfo *results,
+ unw_proc_info_t *ctx) {
+ // Clear results.
+ memset(results, 0, sizeof(*results));
+ PrologInfoStackEntry *rememberStack = NULL;
+
+ // First parse the CIE then FDE instructions.
+ if (!parseInstructions(addressSpace, cieInfo.cieInstructions,
+ cieInfo.cieStart + cieInfo.cieLength, cieInfo,
+ (pint_t)(-1), rememberStack, results, ctx))
+ return false;
+ return parseInstructions(addressSpace, fdeInfo.fdeInstructions,
+ fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
+ upToPC - fdeInfo.pcStart, rememberStack, results,
+ ctx);
+}
+
+/// "Run" the DWARF instructions.
+template <typename A, typename R>
+bool
+CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions,
+ pint_t instructionsEnd,
+ const CIE_Info &cieInfo, pint_t pcoffset,
+ PrologInfoStackEntry *&rememberStack,
+ PrologInfo *results, unw_proc_info_t *ctx) {
+ pint_t p = instructions;
+ uint32_t codeOffset = 0;
+ PrologInfo initialState = *results;
+
+ // See Dwarf Spec, section 6.4.2 for details on unwind opcodes.
+ while (p < instructionsEnd && codeOffset < pcoffset) {
+ uint64_t reg;
+ uint64_t reg2;
+ int64_t offset;
+ uint64_t length;
+ uint8_t opcode = addressSpace.get8(p);
+ uint8_t operand;
+ PrologInfoStackEntry *entry;
+ ++p;
+ switch (opcode) {
+ case DW_CFA_nop:
+ break;
+ case DW_CFA_set_loc:
+ codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
+ cieInfo.pointerEncoding, ctx);
+ break;
+ case DW_CFA_advance_loc1:
+ codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
+ p += 1;
+ break;
+ case DW_CFA_advance_loc2:
+ codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
+ p += 2;
+ break;
+ case DW_CFA_advance_loc4:
+ codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
+ p += 4;
+ break;
+ case DW_CFA_offset_extended:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ offset =
+ addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value = offset;
+ break;
+ case DW_CFA_restore_extended:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg] = initialState.savedRegisters[reg];
+ break;
+ case DW_CFA_undefined:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterUnused;
+ break;
+ case DW_CFA_same_value:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ // "same value" means register was stored in frame, but its current
+ // value has not changed, so no need to restore from frame.
+ // We model this as if the register was never saved.
+ results->savedRegisters[reg].location = kRegisterUnused;
+ break;
+ case DW_CFA_register:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ reg2 = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ if (reg2 > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterInRegister;
+ results->savedRegisters[reg].value = reg2;
+ break;
+ case DW_CFA_remember_state:
+ // avoid operator new, because that would be an upward dependency
+ entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
+ if (entry == NULL)
+ return false;
+
+ entry->next = rememberStack;
+ entry->info = *results;
+ rememberStack = entry;
+ break;
+ case DW_CFA_restore_state:
+ if (rememberStack == NULL)
+ return false;
+ {
+ PrologInfoStackEntry *top = rememberStack;
+ *results = top->info;
+ rememberStack = top->next;
+ free((char *)top);
+ }
+ break;
+ case DW_CFA_def_cfa:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ offset = addressSpace.getULEB128(p, instructionsEnd);
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->cfaRegister = reg;
+ results->cfaRegisterOffset = offset;
+ break;
+ case DW_CFA_def_cfa_register:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->cfaRegister = reg;
+ break;
+ case DW_CFA_def_cfa_offset:
+ results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
+ results->codeOffsetAtStackDecrement = codeOffset;
+ break;
+ case DW_CFA_def_cfa_expression:
+ results->cfaRegister = 0;
+ results->cfaExpression = p;
+ length = addressSpace.getULEB128(p, instructionsEnd);
+ p += length;
+ break;
+ case DW_CFA_expression:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterAtExpression;
+ results->savedRegisters[reg].value = p;
+ length = addressSpace.getULEB128(p, instructionsEnd);
+ p += length;
+ break;
+ case DW_CFA_offset_extended_sf:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ offset =
+ addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value = offset;
+ break;
+ case DW_CFA_def_cfa_sf:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ offset =
+ addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->cfaRegister = reg;
+ results->cfaRegisterOffset = offset;
+ break;
+ case DW_CFA_def_cfa_offset_sf:
+ results->cfaRegisterOffset =
+ addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ results->codeOffsetAtStackDecrement = codeOffset;
+ break;
+ case DW_CFA_val_offset:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ offset =
+ addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
+ results->savedRegisters[reg].value = offset;
+ break;
+ case DW_CFA_val_offset_sf:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ offset =
+ addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
+ results->savedRegisters[reg].value = offset;
+ break;
+ case DW_CFA_val_expression:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg].location = kRegisterIsExpression;
+ results->savedRegisters[reg].value = p;
+ length = addressSpace.getULEB128(p, instructionsEnd);
+ p += length;
+ break;
+ case DW_CFA_GNU_window_save:
+#if defined(__sparc__)
+ for (reg = 8; reg < 16; ++reg) {
+ results->savedRegisters[reg].location = kRegisterInRegister;
+ results->savedRegisters[reg].value = reg + 16;
+ }
+ for (reg = 16; reg < 32; ++reg) {
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value = (reg - 16) * sizeof(typename R::reg_t);
+ }
+ break;
+#else
+ return false;
+#endif
+ case DW_CFA_GNU_args_size:
+ offset = addressSpace.getULEB128(p, instructionsEnd);
+ results->spExtraArgSize = offset;
+ break;
+ case DW_CFA_GNU_negative_offset_extended:
+ reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
+ if (reg > kMaxRegisterNumber)
+ return false;
+ offset =
+ addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value = -offset;
+ break;
+ default:
+ operand = opcode & 0x3F;
+ switch (opcode & 0xC0) {
+ case DW_CFA_offset:
+ reg = R::dwarf2regno(operand);
+ if (reg > kMaxRegisterNumber)
+ return false;
+ offset = addressSpace.getULEB128(p, instructionsEnd) *
+ cieInfo.dataAlignFactor;
+ results->savedRegisters[reg].location = kRegisterInCFA;
+ results->savedRegisters[reg].value = offset;
+ break;
+ case DW_CFA_advance_loc:
+ codeOffset += operand * cieInfo.codeAlignFactor;
+ break;
+ case DW_CFA_restore:
+ reg = R::dwarf2regno(operand);
+ if (reg > kMaxRegisterNumber)
+ return false;
+ results->savedRegisters[reg] = initialState.savedRegisters[reg];
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace _Unwind
+
+#endif // __DWARF_PARSER_HPP__
Index: contrib/netbsd-unwind/LICENSE.TXT
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/LICENSE.TXT
@@ -0,0 +1,76 @@
+==============================================================================
+libc++abi License
+==============================================================================
+
+The libc++abi library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: contrib/netbsd-unwind/Makefile.inc
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/Makefile.inc
@@ -0,0 +1,18 @@
+# $NetBSD: Makefile.inc,v 1.11 2015/01/29 20:45:16 joerg Exp $
+
+.PATH: ${NETBSDSRCDIR}/sys/lib/libunwind
+
+SRCS+= libunwind.cxx \
+ unwind_registers.S
+
+INCS+= unwind.h
+
+COPTS.libunwind.cxx+= ${${ACTIVE_CXX} == "gcc":? -std=c++0x : -std=c++11 }
+COPTS.libunwind.cxx+= -funwind-tables -fno-rtti
+COPTS.libunwind.cxx+= -fno-exceptions -fvisibility=hidden
+COPTS.libunwind.cxx+= -Wno-old-style-cast
+CPPFLAGS.libunwind.cxx+=-I${NETBSDSRCDIR}/sys/lib/libunwind
+
+.if ${LIBC_MACHINE_CPU} == "arm"
+AFLAGS.unwind_registers.S+= ${${ACTIVE_CC} == "clang":? -mfpu=vfp3 :}
+.endif
Index: contrib/netbsd-unwind/Registers.hpp
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/Registers.hpp
@@ -0,0 +1,1144 @@
+//===----------------------------- Registers.hpp --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//
+// Models register sets for supported processors.
+//
+//===----------------------------------------------------------------------===//
+#ifndef __REGISTERS_HPP__
+#define __REGISTERS_HPP__
+
+#include <cassert>
+#include <cstdint>
+
+#define __dso_hidden
+
+namespace _Unwind {
+
+enum {
+ REGNO_X86_EAX = 0,
+ REGNO_X86_ECX = 1,
+ REGNO_X86_EDX = 2,
+ REGNO_X86_EBX = 3,
+ REGNO_X86_ESP = 4,
+ REGNO_X86_EBP = 5,
+ REGNO_X86_ESI = 6,
+ REGNO_X86_EDI = 7,
+ REGNO_X86_EIP = 8,
+};
+
+class Registers_x86 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_X86_EIP,
+ LAST_RESTORE_REG = REGNO_X86_EIP,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_x86();
+
+ static int dwarf2regno(int num) { return num; }
+
+ bool validRegister(int num) const {
+ return num >= REGNO_X86_EAX && num <= REGNO_X86_EDI;
+ }
+
+ uint32_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint32_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint32_t getIP() const { return reg[REGNO_X86_EIP]; }
+
+ void setIP(uint32_t value) { reg[REGNO_X86_EIP] = value; }
+
+ uint32_t getSP() const { return reg[REGNO_X86_ESP]; }
+
+ void setSP(uint32_t value) { reg[REGNO_X86_ESP] = value; }
+
+ bool validFloatVectorRegister(int num) const { return false; }
+
+ void copyFloatVectorRegister(int num, uint32_t addr) {
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_X86_EIP + 1];
+};
+
+enum {
+ REGNO_X86_64_RAX = 0,
+ REGNO_X86_64_RDX = 1,
+ REGNO_X86_64_RCX = 2,
+ REGNO_X86_64_RBX = 3,
+ REGNO_X86_64_RSI = 4,
+ REGNO_X86_64_RDI = 5,
+ REGNO_X86_64_RBP = 6,
+ REGNO_X86_64_RSP = 7,
+ REGNO_X86_64_R8 = 8,
+ REGNO_X86_64_R9 = 9,
+ REGNO_X86_64_R10 = 10,
+ REGNO_X86_64_R11 = 11,
+ REGNO_X86_64_R12 = 12,
+ REGNO_X86_64_R13 = 13,
+ REGNO_X86_64_R14 = 14,
+ REGNO_X86_64_R15 = 15,
+ REGNO_X86_64_RIP = 16,
+};
+
+class Registers_x86_64 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_X86_64_RIP,
+ LAST_RESTORE_REG = REGNO_X86_64_RIP,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_x86_64();
+
+ static int dwarf2regno(int num) { return num; }
+
+ bool validRegister(int num) const {
+ return num >= REGNO_X86_64_RAX && num <= REGNO_X86_64_R15;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_X86_64_RIP]; }
+
+ void setIP(uint64_t value) { reg[REGNO_X86_64_RIP] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_X86_64_RSP]; }
+
+ void setSP(uint64_t value) { reg[REGNO_X86_64_RSP] = value; }
+
+ bool validFloatVectorRegister(int num) const { return false; }
+
+ void copyFloatVectorRegister(int num, uint64_t addr) {
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint64_t reg[REGNO_X86_64_RIP + 1];
+};
+
+enum {
+ DWARF_PPC32_R0 = 0,
+ DWARF_PPC32_R31 = 31,
+ DWARF_PPC32_F0 = 32,
+ DWARF_PPC32_F31 = 63,
+ DWARF_PPC32_LR = 65,
+ DWARF_PPC32_CR = 70,
+ DWARF_PPC32_V0 = 77,
+ DWARF_PPC32_V31 = 108,
+
+ REGNO_PPC32_R0 = 0,
+ REGNO_PPC32_R1 = 1,
+ REGNO_PPC32_R31 = 31,
+ REGNO_PPC32_LR = 32,
+ REGNO_PPC32_CR = 33,
+ REGNO_PPC32_SRR0 = 34,
+
+ REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
+ REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
+ REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
+ REGNO_PPC32_V31 = REGNO_PPC32_V0 + 31,
+};
+
+class Registers_ppc32 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_PPC32_V31,
+ LAST_RESTORE_REG = REGNO_PPC32_V31,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_ppc32();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_PPC32_R0 && num <= DWARF_PPC32_R31)
+ return REGNO_PPC32_R0 + (num - DWARF_PPC32_R0);
+ if (num >= DWARF_PPC32_F0 && num <= DWARF_PPC32_F31)
+ return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
+ if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
+ return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
+ switch (num) {
+ case DWARF_PPC32_LR:
+ return REGNO_PPC32_LR;
+ case DWARF_PPC32_CR:
+ return REGNO_PPC32_CR;
+ default:
+ return LAST_REGISTER + 1;
+ }
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= LAST_RESTORE_REG;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_PPC32_SRR0]; }
+
+ void setIP(uint64_t value) { reg[REGNO_PPC32_SRR0] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_PPC32_R1]; }
+
+ void setSP(uint64_t value) { reg[REGNO_PPC32_R1] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31) ||
+ (num >= REGNO_PPC32_V0 && num <= REGNO_PPC32_V31);
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ if (num >= REGNO_PPC32_F0 && num <= REGNO_PPC32_F31)
+ memcpy(fpreg + (num - REGNO_PPC32_F0), addr, sizeof(fpreg[0]));
+ else
+ memcpy(vecreg + (num - REGNO_PPC32_V0), addr, sizeof(vecreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ struct vecreg_t {
+ uint64_t low, high;
+ };
+ uint32_t reg[REGNO_PPC32_SRR0 + 1];
+ uint32_t dummy;
+ uint64_t fpreg[32];
+ vecreg_t vecreg[64];
+};
+
+enum {
+ DWARF_AARCH64_X0 = 0,
+ DWARF_AARCH64_X30 = 30,
+ DWARF_AARCH64_SP = 31,
+ DWARF_AARCH64_ELR_MODE = 33,
+ DWARF_AARCH64_V0 = 64,
+ DWARF_AARCH64_V31 = 95,
+
+ REGNO_AARCH64_X0 = 0,
+ REGNO_AARCH64_X30 = 30,
+ REGNO_AARCH64_SP = 31,
+ REGNO_AARCH64_ELR_MODE = 32,
+ REGNO_AARCH64_V0 = 33,
+ REGNO_AARCH64_V31 = 64,
+};
+
+class Registers_aarch64 {
+public:
+ enum {
+ LAST_RESTORE_REG = REGNO_AARCH64_V31,
+ LAST_REGISTER = REGNO_AARCH64_V31,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_aarch64();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_AARCH64_X0 && num <= DWARF_AARCH64_X30)
+ return REGNO_AARCH64_X0 + (num - DWARF_AARCH64_X0);
+ if (num == DWARF_AARCH64_SP)
+ return REGNO_AARCH64_SP;
+ if (num == DWARF_AARCH64_ELR_MODE)
+ return REGNO_AARCH64_ELR_MODE;
+ if (num >= DWARF_AARCH64_V0 && num <= DWARF_AARCH64_V31)
+ return REGNO_AARCH64_V0 + (num - DWARF_AARCH64_V0);
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= LAST_RESTORE_REG;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_AARCH64_X30]; }
+
+ void setIP(uint64_t value) { reg[REGNO_AARCH64_X30] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_AARCH64_SP]; }
+
+ void setSP(uint64_t value) { reg[REGNO_AARCH64_SP] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return (num >= REGNO_AARCH64_V0 && num <= REGNO_AARCH64_V31);
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(vecreg + (num - REGNO_AARCH64_V0), addr, sizeof(vecreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ struct vecreg_t {
+ uint64_t low, high;
+ };
+ uint64_t reg[REGNO_AARCH64_ELR_MODE + 1];
+ vecreg_t vecreg[32];
+};
+
+enum {
+ DWARF_ARM32_R0 = 0,
+ DWARF_ARM32_R15 = 15,
+ DWARF_ARM32_SPSR = 128,
+ DWARF_ARM32_OLD_S0 = 64,
+ DWARF_ARM32_OLD_S31 = 91,
+ DWARF_ARM32_D0 = 256,
+ DWARF_ARM32_D31 = 287,
+ REGNO_ARM32_R0 = 0,
+ REGNO_ARM32_SP = 13,
+ REGNO_ARM32_R15 = 15,
+ REGNO_ARM32_SPSR = 16,
+ REGNO_ARM32_D0 = 17,
+ REGNO_ARM32_D15 = 32,
+ REGNO_ARM32_D31 = 48,
+};
+
+class Registers_arm32 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_ARM32_D31,
+ LAST_RESTORE_REG = REGNO_ARM32_D31,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_arm32();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15)
+ return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0);
+ if (num == DWARF_ARM32_SPSR)
+ return REGNO_ARM32_SPSR;
+ if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31)
+ return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0);
+ if (num >= DWARF_ARM32_OLD_S0 && num <= DWARF_ARM32_OLD_S31) {
+ assert(num % 2 == 0);
+ return REGNO_ARM32_D0 + (num - DWARF_ARM32_OLD_S0) / 2;
+ }
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_ARM32_SPSR;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_ARM32_R15]; }
+
+ void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_ARM32_SP]; }
+
+ void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_D31);
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ if (num <= REGNO_ARM32_D15) {
+ if ((flags & 1) == 0) {
+ lazyVFP1();
+ flags |= 1;
+ }
+ } else {
+ if ((flags & 2) == 0) {
+ lazyVFP3();
+ flags |= 2;
+ }
+ }
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void lazyVFP1();
+ __dso_hidden void lazyVFP3();
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_ARM32_SPSR + 1];
+ uint32_t flags;
+ uint64_t fpreg[32];
+};
+
+enum {
+ DWARF_VAX_R0 = 0,
+ DWARF_VAX_R15 = 15,
+ DWARF_VAX_PSW = 16,
+
+ REGNO_VAX_R0 = 0,
+ REGNO_VAX_R14 = 14,
+ REGNO_VAX_R15 = 15,
+ REGNO_VAX_PSW = 16,
+};
+
+class Registers_vax {
+public:
+ enum {
+ LAST_REGISTER = REGNO_VAX_PSW,
+ LAST_RESTORE_REG = REGNO_VAX_PSW,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_vax();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15)
+ return REGNO_VAX_R0 + (num - DWARF_VAX_R0);
+ if (num == DWARF_VAX_PSW)
+ return REGNO_VAX_PSW;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= LAST_RESTORE_REG;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_VAX_R15]; }
+
+ void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_VAX_R14]; }
+
+ void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return false;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_VAX_PSW + 1];
+};
+
+enum {
+ DWARF_M68K_A0 = 0,
+ DWARF_M68K_A7 = 7,
+ DWARF_M68K_D0 = 8,
+ DWARF_M68K_D7 = 15,
+ DWARF_M68K_FP0 = 16,
+ DWARF_M68K_FP7 = 23,
+ DWARF_M68K_PC = 24,
+
+ REGNO_M68K_A0 = 0,
+ REGNO_M68K_A7 = 7,
+ REGNO_M68K_D0 = 8,
+ REGNO_M68K_D7 = 15,
+ REGNO_M68K_PC = 16,
+ REGNO_M68K_FP0 = 17,
+ REGNO_M68K_FP7 = 24,
+};
+
+class Registers_M68K {
+public:
+ enum {
+ LAST_REGISTER = REGNO_M68K_FP7,
+ LAST_RESTORE_REG = REGNO_M68K_FP7,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_M68K();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7)
+ return REGNO_M68K_A0 + (num - DWARF_M68K_A0);
+ if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7)
+ return REGNO_M68K_D0 + (num - DWARF_M68K_D0);
+ if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7)
+ return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0);
+ if (num == DWARF_M68K_PC)
+ return REGNO_M68K_PC;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_M68K_PC;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_M68K_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_M68K_A7]; }
+
+ void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ assert(validFloatVectorRegister(num));
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ typedef uint32_t fpreg_t[3];
+
+ uint32_t reg[REGNO_M68K_PC + 1];
+ uint32_t dummy;
+ fpreg_t fpreg[8];
+};
+
+enum {
+ DWARF_SH3_R0 = 0,
+ DWARF_SH3_R15 = 15,
+ DWARF_SH3_PC = 16,
+ DWARF_SH3_PR = 17,
+
+ REGNO_SH3_R0 = 0,
+ REGNO_SH3_R15 = 15,
+ REGNO_SH3_PC = 16,
+ REGNO_SH3_PR = 17,
+};
+
+class Registers_SH3 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_SH3_PR,
+ LAST_RESTORE_REG = REGNO_SH3_PR,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_SH3();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15)
+ return REGNO_SH3_R0 + (num - DWARF_SH3_R0);
+ if (num == DWARF_SH3_PC)
+ return REGNO_SH3_PC;
+ if (num == DWARF_SH3_PR)
+ return REGNO_SH3_PR;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_SH3_PR;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_SH3_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_SH3_R15]; }
+
+ void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; }
+
+ bool validFloatVectorRegister(int num) const { return false; }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {}
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_SH3_PR + 1];
+};
+
+enum {
+ DWARF_SPARC64_R0 = 0,
+ DWARF_SPARC64_R31 = 31,
+ DWARF_SPARC64_PC = 32,
+
+ REGNO_SPARC64_R0 = 0,
+ REGNO_SPARC64_R14 = 14,
+ REGNO_SPARC64_R15 = 15,
+ REGNO_SPARC64_R31 = 31,
+ REGNO_SPARC64_PC = 32,
+};
+
+class Registers_SPARC64 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_SPARC64_PC,
+ LAST_RESTORE_REG = REGNO_SPARC64_PC,
+ RETURN_OFFSET = 8,
+ RETURN_MASK = 0,
+ };
+ typedef uint64_t reg_t;
+
+ __dso_hidden Registers_SPARC64();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31)
+ return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0);
+ if (num == DWARF_SPARC64_PC)
+ return REGNO_SPARC64_PC;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_SPARC64_PC;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; }
+
+ void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; }
+
+ bool validFloatVectorRegister(int num) const { return false; }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {}
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint64_t reg[REGNO_SPARC64_PC + 1];
+};
+
+enum {
+ DWARF_SPARC_R0 = 0,
+ DWARF_SPARC_R31 = 31,
+ DWARF_SPARC_PC = 32,
+
+ REGNO_SPARC_R0 = 0,
+ REGNO_SPARC_R14 = 14,
+ REGNO_SPARC_R15 = 15,
+ REGNO_SPARC_R31 = 31,
+ REGNO_SPARC_PC = 32,
+};
+
+class Registers_SPARC {
+public:
+ enum {
+ LAST_REGISTER = REGNO_SPARC_PC,
+ LAST_RESTORE_REG = REGNO_SPARC_PC,
+ RETURN_OFFSET = 8,
+ RETURN_MASK = 0,
+ };
+ typedef uint32_t reg_t;
+
+ __dso_hidden Registers_SPARC();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31)
+ return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0);
+ if (num == DWARF_SPARC_PC)
+ return REGNO_SPARC_PC;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_SPARC_PC;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_SPARC_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_SPARC_R14]; }
+
+ void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; }
+
+ bool validFloatVectorRegister(int num) const { return false; }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {}
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_SPARC_PC + 1];
+};
+
+enum {
+ DWARF_ALPHA_R0 = 0,
+ DWARF_ALPHA_R30 = 30,
+ DWARF_ALPHA_F0 = 32,
+ DWARF_ALPHA_F30 = 62,
+
+ REGNO_ALPHA_R0 = 0,
+ REGNO_ALPHA_R26 = 26,
+ REGNO_ALPHA_R30 = 30,
+ REGNO_ALPHA_PC = 31,
+ REGNO_ALPHA_F0 = 32,
+ REGNO_ALPHA_F30 = 62,
+};
+
+class Registers_Alpha {
+public:
+ enum {
+ LAST_REGISTER = REGNO_ALPHA_F30,
+ LAST_RESTORE_REG = REGNO_ALPHA_F30,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+ typedef uint32_t reg_t;
+
+ __dso_hidden Registers_Alpha();
+
+ static int dwarf2regno(int num) { return num; }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= REGNO_ALPHA_PC;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; }
+
+ void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ assert(validFloatVectorRegister(num));
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint64_t reg[REGNO_ALPHA_PC + 1];
+ uint64_t fpreg[31];
+};
+
+enum {
+ DWARF_HPPA_R1 = 1,
+ DWARF_HPPA_R31 = 31,
+ DWARF_HPPA_FR4L = 32,
+ DWARF_HPPA_FR31H = 87,
+
+ REGNO_HPPA_PC = 0,
+ REGNO_HPPA_R1 = 1,
+ REGNO_HPPA_R2 = 2,
+ REGNO_HPPA_R30 = 30,
+ REGNO_HPPA_R31 = 31,
+ REGNO_HPPA_FR4L = 32,
+ REGNO_HPPA_FR31H = 87,
+};
+
+class Registers_HPPA {
+public:
+ enum {
+ LAST_REGISTER = REGNO_HPPA_FR31H,
+ LAST_RESTORE_REG = REGNO_HPPA_FR31H,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 3,
+ };
+
+ __dso_hidden Registers_HPPA();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31)
+ return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1);
+ if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H)
+ return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H);
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_HPPA_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_HPPA_R30]; }
+
+ void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ assert(validFloatVectorRegister(num));
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_HPPA_R31 + 1];
+ uint32_t fpreg[56];
+};
+
+enum {
+ DWARF_MIPS_R1 = 0,
+ DWARF_MIPS_R31 = 31,
+ DWARF_MIPS_F0 = 32,
+ DWARF_MIPS_F31 = 63,
+
+ REGNO_MIPS_PC = 0,
+ REGNO_MIPS_R1 = 0,
+ REGNO_MIPS_R29 = 29,
+ REGNO_MIPS_R31 = 31,
+ REGNO_MIPS_F0 = 33,
+ REGNO_MIPS_F31 = 64
+};
+
+class Registers_MIPS {
+public:
+ enum {
+ LAST_REGISTER = REGNO_MIPS_F31,
+ LAST_RESTORE_REG = REGNO_MIPS_F31,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_MIPS();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31)
+ return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1);
+ if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31)
+ return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0);
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_MIPS_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_MIPS_R29]; }
+
+ void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ assert(validFloatVectorRegister(num));
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_MIPS_R31 + 1];
+ uint64_t fpreg[32];
+};
+
+enum {
+ DWARF_MIPS64_R1 = 0,
+ DWARF_MIPS64_R31 = 31,
+ DWARF_MIPS64_F0 = 32,
+ DWARF_MIPS64_F31 = 63,
+
+ REGNO_MIPS64_PC = 0,
+ REGNO_MIPS64_R1 = 0,
+ REGNO_MIPS64_R29 = 29,
+ REGNO_MIPS64_R31 = 31,
+ REGNO_MIPS64_F0 = 33,
+ REGNO_MIPS64_F31 = 64
+};
+
+class Registers_MIPS64 {
+public:
+ enum {
+ LAST_REGISTER = REGNO_MIPS64_F31,
+ LAST_RESTORE_REG = REGNO_MIPS64_F31,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_MIPS64();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31)
+ return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1);
+ if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31)
+ return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0);
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; }
+
+ void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; }
+
+ void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ assert(validFloatVectorRegister(num));
+ const void *addr = reinterpret_cast<const void *>(addr_);
+ memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0]));
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint64_t reg[REGNO_MIPS64_R31 + 1];
+ uint64_t fpreg[32];
+};
+
+enum {
+ DWARF_OR1K_R0 = 0,
+ DWARF_OR1K_SP = 1,
+ DWARF_OR1K_LR = 9,
+ DWARF_OR1K_R31 = 31,
+ DWARF_OR1K_FPCSR = 32,
+
+ REGNO_OR1K_R0 = 0,
+ REGNO_OR1K_SP = 1,
+ REGNO_OR1K_LR = 9,
+ REGNO_OR1K_R31 = 31,
+ REGNO_OR1K_FPCSR = 32,
+};
+
+class Registers_or1k {
+public:
+ enum {
+ LAST_REGISTER = REGNO_OR1K_FPCSR,
+ LAST_RESTORE_REG = REGNO_OR1K_FPCSR,
+ RETURN_OFFSET = 0,
+ RETURN_MASK = 0,
+ };
+
+ __dso_hidden Registers_or1k();
+
+ static int dwarf2regno(int num) {
+ if (num >= DWARF_OR1K_R0 && num <= DWARF_OR1K_R31)
+ return REGNO_OR1K_R0 + (num - DWARF_OR1K_R0);
+ if (num == DWARF_OR1K_FPCSR)
+ return REGNO_OR1K_FPCSR;
+ return LAST_REGISTER + 1;
+ }
+
+ bool validRegister(int num) const {
+ return num >= 0 && num <= LAST_RESTORE_REG;
+ }
+
+ uint64_t getRegister(int num) const {
+ assert(validRegister(num));
+ return reg[num];
+ }
+
+ void setRegister(int num, uint64_t value) {
+ assert(validRegister(num));
+ reg[num] = value;
+ }
+
+ uint64_t getIP() const { return reg[REGNO_OR1K_LR]; }
+
+ void setIP(uint64_t value) { reg[REGNO_OR1K_LR] = value; }
+
+ uint64_t getSP() const { return reg[REGNO_OR1K_SP]; }
+
+ void setSP(uint64_t value) { reg[REGNO_OR1K_SP] = value; }
+
+ bool validFloatVectorRegister(int num) const {
+ return false;
+ }
+
+ void copyFloatVectorRegister(int num, uint64_t addr_) {
+ }
+
+ __dso_hidden void jumpto() const __dead2;
+
+private:
+ uint32_t reg[REGNO_OR1K_FPCSR + 1];
+};
+
+#if __i386__
+typedef Registers_x86 NativeUnwindRegisters;
+#elif __x86_64__
+typedef Registers_x86_64 NativeUnwindRegisters;
+#elif __powerpc__
+typedef Registers_ppc32 NativeUnwindRegisters;
+#elif __aarch64__
+typedef Registers_aarch64 NativeUnwindRegisters;
+#elif __arm__
+typedef Registers_arm32 NativeUnwindRegisters;
+#elif __vax__
+typedef Registers_vax NativeUnwindRegisters;
+#elif __m68k__
+typedef Registers_M68K NativeUnwindRegisters;
+#elif __mips_n64 || __mips_n32
+typedef Registers_MIPS64 NativeUnwindRegisters;
+#elif __mips__
+typedef Registers_MIPS NativeUnwindRegisters;
+#elif __sh3__
+typedef Registers_SH3 NativeUnwindRegisters;
+#elif __sparc64__
+typedef Registers_SPARC64 NativeUnwindRegisters;
+#elif __sparc__
+typedef Registers_SPARC NativeUnwindRegisters;
+#elif __alpha__
+typedef Registers_Alpha NativeUnwindRegisters;
+#elif __hppa__
+typedef Registers_HPPA NativeUnwindRegisters;
+#elif __or1k__
+typedef Registers_or1k NativeUnwindRegisters;
+#endif
+} // namespace _Unwind
+
+#endif // __REGISTERS_HPP__
Index: contrib/netbsd-unwind/UnwindCursor.hpp
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/UnwindCursor.hpp
@@ -0,0 +1,142 @@
+//===------------------------- 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
+//===----------------------------------------------------------------------===//
+
+#ifndef __UNWINDCURSOR_HPP__
+#define __UNWINDCURSOR_HPP__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "AddressSpace.hpp"
+#include "DwarfInstructions.hpp"
+#include "Registers.hpp"
+
+namespace _Unwind {
+
+template <typename A, typename R> class UnwindCursor {
+public:
+ UnwindCursor(R &regs, A &as)
+ : fRegisters(regs), fAddressSpace(as), fUnwindInfoMissing(false),
+ fIsSignalFrame(false) {
+ memset(&fInfo, 0, sizeof(fInfo));
+ }
+
+ uint64_t getIP() const { return fRegisters.getIP(); }
+
+ void setIP(uint64_t value) { return fRegisters.setIP(value); }
+
+ uint64_t getSP() const { return fRegisters.getSP(); }
+
+ void setSP(uint64_t value) { return fRegisters.setSP(value); }
+
+ bool validReg(int regNum) { return fRegisters.validRegister(regNum); }
+
+ uint64_t getReg(int regNum) { return fRegisters.getRegister(regNum); }
+
+ void setReg(int regNum, uint64_t value) {
+ fRegisters.setRegister(regNum, value);
+ }
+
+ step_result step() {
+ // Bottom of stack is defined as having no more unwind info.
+ if (fUnwindInfoMissing)
+ return UNW_STEP_END;
+
+ // Apply unwinding to register set.
+ switch (this->stepWithDwarfFDE()) {
+ case UNW_STEP_FAILED:
+ return UNW_STEP_FAILED;
+ case UNW_STEP_END:
+ return UNW_STEP_END;
+ case UNW_STEP_SUCCESS:
+ this->setInfoBasedOnIPRegister(true);
+ if (fUnwindInfoMissing)
+ return UNW_STEP_END;
+
+ if (fInfo.extra_args)
+ setSP(getSP() + fInfo.extra_args);
+ return UNW_STEP_SUCCESS;
+ }
+ __builtin_unreachable();
+ }
+
+ void getInfo(unw_proc_info_t *info) { *info = fInfo; }
+
+ bool isSignalFrame() { return fIsSignalFrame; }
+ void setInfoBasedOnIPRegister(bool isReturnAddress = false);
+
+ void jumpto() { fRegisters.jumpto(); }
+
+private:
+ typedef typename A::pint_t pint_t;
+ typedef uint32_t EncodedUnwindInfo;
+
+ bool getInfoFromDwarfSection(pint_t, pint_t, uint32_t, uint32_t);
+
+ step_result stepWithDwarfFDE() {
+ return DwarfInstructions<A, R>::stepWithDwarf(
+ fAddressSpace, this->getIP(), fInfo.unwind_info, fRegisters, &fInfo);
+ }
+
+ unw_proc_info_t fInfo;
+ R fRegisters;
+ A &fAddressSpace;
+ bool fUnwindInfoMissing;
+ bool fIsSignalFrame;
+};
+
+template <typename A, typename R>
+void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
+ pint_t pc = this->getIP();
+
+ // 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;
+
+ pint_t fdeStart, data_base;
+ if (!fAddressSpace.findFDE(pc, fdeStart, data_base)) {
+ fUnwindInfoMissing = true;
+ return;
+ }
+ fInfo.data_base = data_base;
+
+ typename CFI_Parser<A, R>::FDE_Info fdeInfo;
+ typename CFI_Parser<A, R>::CIE_Info cieInfo;
+ CFI_Parser<A, R>::decodeFDE(fAddressSpace, fdeStart, &fdeInfo, &cieInfo,
+ &fInfo);
+ if (pc < fdeInfo.pcStart || pc > fdeInfo.pcEnd) {
+ fUnwindInfoMissing = true;
+ return;
+ }
+ fInfo.start_ip = fdeInfo.pcStart;
+
+ typename CFI_Parser<A, R>::PrologInfo prolog;
+ if (!CFI_Parser<A, R>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo,
+ pc, &prolog, &fInfo)) {
+ fUnwindInfoMissing = true;
+ return;
+ }
+ // Save off parsed FDE info
+ fInfo.end_ip = fdeInfo.pcEnd;
+ fInfo.lsda = fdeInfo.lsda;
+ fInfo.handler = cieInfo.personality;
+ fInfo.extra_args = prolog.spExtraArgSize;
+ fInfo.unwind_info = fdeInfo.fdeStart;
+}
+
+}; // namespace _Unwind
+
+#endif // __UNWINDCURSOR_HPP__
Index: contrib/netbsd-unwind/libunwind.cxx
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/libunwind.cxx
@@ -0,0 +1,392 @@
+//===--------------------------- libuwind.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 C++ ABI Exception Handling Level 1 as documented at:
+// http://mentorembedded.github.io/cxx-abi/abi-eh.html
+//
+//===----------------------------------------------------------------------===//
+
+#define _UNWIND_GCC_EXTENSIONS
+
+#include "unwind.h"
+
+#include "UnwindCursor.hpp"
+
+using namespace _Unwind;
+
+typedef CFI_Parser<LocalAddressSpace, NativeUnwindRegisters> MyCFIParser;
+
+// Internal object representing the address space of this process.
+static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange);
+
+typedef UnwindCursor<LocalAddressSpace, NativeUnwindRegisters> ThisUnwindCursor;
+
+static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor,
+ struct _Unwind_Exception *exc) {
+ cursor.setInfoBasedOnIPRegister();
+
+ // Walk frames looking for a place to stop.
+ for (;;) {
+ // Get next frame.
+ // First frame is _Unwind_RaiseException and skipped.
+ switch (cursor.step()) {
+ case UNW_STEP_END:
+ return _URC_END_OF_STACK;
+ case UNW_STEP_FAILED:
+ return _URC_FATAL_PHASE1_ERROR;
+ case UNW_STEP_SUCCESS:
+ break;
+ }
+
+ // Check if there is a personality routine for this frame.
+ unw_proc_info_t frameInfo;
+ cursor.getInfo(&frameInfo);
+ if (frameInfo.end_ip == 0)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ if (frameInfo.handler == 0)
+ continue; // No personality routine, so try next frame.
+
+ __personality_routine p = (__personality_routine)(frameInfo.handler);
+ _Unwind_Reason_Code result = (*p)(1, _UA_SEARCH_PHASE, exc->exception_class,
+ exc, (struct _Unwind_Context *)(&cursor));
+
+ switch (result) {
+ case _URC_HANDLER_FOUND:
+ // This is either a catch clause or a local variable
+ // with destructor.
+ // Stop search and remember the frame for phase 2.
+ exc->private_2 = cursor.getSP();
+ return _URC_NO_REASON;
+
+ case _URC_CONTINUE_UNWIND:
+ // Continue unwinding
+ break;
+
+ default:
+ // Bad personality routine.
+ return _URC_FATAL_PHASE1_ERROR;
+ }
+ }
+}
+
+static _Unwind_Reason_Code unwind_phase2(ThisUnwindCursor &cursor,
+ struct _Unwind_Exception *exc) {
+ cursor.setInfoBasedOnIPRegister();
+
+ // Walk frames until the frame selected in phase 1 is reached.
+ for (;;) {
+ // Get next frame.
+ // First frame is _Unwind_RaiseException and skipped.
+ switch (cursor.step()) {
+ case UNW_STEP_END:
+ return _URC_END_OF_STACK;
+ case UNW_STEP_FAILED:
+ return _URC_FATAL_PHASE2_ERROR;
+ case UNW_STEP_SUCCESS:
+ break;
+ }
+
+ unw_proc_info_t frameInfo;
+ cursor.getInfo(&frameInfo);
+ if (frameInfo.end_ip == 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ if (frameInfo.handler == 0)
+ continue; // No personality routine, continue.
+
+ uintptr_t sp = cursor.getSP();
+
+ _Unwind_Action action = _UA_CLEANUP_PHASE;
+ // If this frame was selected in phase 1,
+ // inform the personality routine.
+ if (sp == exc->private_2)
+ action = (_Unwind_Action)(action | _UA_HANDLER_FRAME);
+ __personality_routine p = (__personality_routine)(frameInfo.handler);
+ _Unwind_Reason_Code result = (*p)(1, action, exc->exception_class, exc,
+ (struct _Unwind_Context *)(&cursor));
+ switch (result) {
+ case _URC_CONTINUE_UNWIND:
+ // Continue unwinding unless the selected frame passed.
+ if (sp == exc->private_2)
+ return _URC_FATAL_PHASE2_ERROR;
+ break;
+ case _URC_INSTALL_CONTEXT:
+ // Transfer control to landing pad.
+ cursor.jumpto();
+ default:
+ // Bad personality routine.
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+ }
+}
+
+static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor,
+ struct _Unwind_Exception *exc,
+ _Unwind_Stop_Fn stop,
+ void *stop_arg) {
+ _Unwind_Action action;
+ cursor.setInfoBasedOnIPRegister();
+
+ // Walk frames until the frame selected in phase 1 is reached.
+ for (;;) {
+ // Get next frame.
+ // First frame is _Unwind_RaiseException and skipped.
+ switch (cursor.step()) {
+ case UNW_STEP_END:
+ case UNW_STEP_FAILED:
+ // End of stack or error condition.
+ // Call the stop function one last time.
+ action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE |
+ _UA_END_OF_STACK);
+ (*stop)(1, action, exc->exception_class, exc,
+ (struct _Unwind_Context *)(&cursor), stop_arg);
+
+ // Didn't stop at the expected frame, so return error.
+ return _URC_FATAL_PHASE2_ERROR;
+
+ case UNW_STEP_SUCCESS:
+ break;
+ }
+
+ unw_proc_info_t frameInfo;
+ cursor.getInfo(&frameInfo);
+ if (frameInfo.end_ip == 0)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ // Call stop function for each frame
+ action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
+ _Unwind_Reason_Code result =
+ (*stop)(1, action, exc->exception_class, exc,
+ (struct _Unwind_Context *)(&cursor), stop_arg);
+ if (result != _URC_NO_REASON)
+ return _URC_FATAL_PHASE2_ERROR;
+
+ if (frameInfo.handler == 0)
+ continue; // No personality routine, continue.
+
+ __personality_routine p = (__personality_routine)(frameInfo.handler);
+ result = (*p)(1, action, exc->exception_class, exc,
+ (struct _Unwind_Context *)(&cursor));
+
+ switch (result) {
+ case _URC_CONTINUE_UNWIND:
+ // Destructors called, continue.
+ break;
+ case _URC_INSTALL_CONTEXT:
+ // Transfer control to landing pad.
+ cursor.jumpto();
+ default:
+ // Bad personality routine.
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+ }
+}
+
+_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor1(registers, sThisAddressSpace);
+ ThisUnwindCursor cursor2(registers, sThisAddressSpace);
+
+ // Mark this as a non-forced unwind for _Unwind_Resume().
+ exc->private_1 = 0;
+ exc->private_2 = 0;
+
+ // Phase 1: searching.
+ _Unwind_Reason_Code phase1 = unwind_phase1(cursor1, exc);
+ if (phase1 != _URC_NO_REASON)
+ return phase1;
+
+ // Phase 2: cleaning up.
+ return unwind_phase2(cursor2, exc);
+}
+
+_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
+ _Unwind_Stop_Fn stop, void *stop_arg) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor(registers, sThisAddressSpace);
+
+ // Mark this as forced unwind for _Unwind_Resume().
+ exc->private_1 = (uintptr_t)stop;
+ exc->private_2 = (uintptr_t)stop_arg;
+
+ return unwind_phase2_forced(cursor, exc, stop, stop_arg);
+}
+
+void _Unwind_Resume(struct _Unwind_Exception *exc) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor(registers, sThisAddressSpace);
+
+ if (exc->private_1 != 0)
+ unwind_phase2_forced(cursor, exc, (_Unwind_Stop_Fn)exc->private_1,
+ (void *)exc->private_2);
+ else
+ unwind_phase2(cursor, exc);
+ abort();
+}
+
+_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exc) {
+ // This is a re-throw, if this is a non-forced unwind
+ // and the stopping place was found.
+ // In that case, call _Unwind_RaiseException() as if
+ // it was a new exception.
+
+ if (exc->private_1 != 0)
+ _Unwind_Resume(exc);
+
+ // This can return if there is no catch clause.
+ // In that case, __cxa_rethrow is expected to call std::terminate().
+ return _Unwind_RaiseException(exc);
+}
+
+void _Unwind_DeleteException(struct _Unwind_Exception *exc) {
+ if (exc->exception_cleanup != NULL)
+ (*exc->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ return cursor->getReg(index);
+}
+
+void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+ uintptr_t new_value) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ cursor->setReg(index, new_value);
+}
+
+uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ return cursor->getIP();
+}
+
+uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ *isSignalFrame = cursor->isSignalFrame() ? 1 : 0;
+ return cursor->getIP();
+}
+
+void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ cursor->setIP(new_value);
+ unw_proc_info_t info;
+ cursor->getInfo(&info);
+ cursor->setInfoBasedOnIPRegister(false);
+}
+
+uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ unw_proc_info_t frameInfo;
+ cursor->getInfo(&frameInfo);
+ return frameInfo.end_ip ? frameInfo.start_ip : 0;
+}
+
+uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ unw_proc_info_t frameInfo;
+ cursor->getInfo(&frameInfo);
+ return frameInfo.end_ip ? frameInfo.lsda : 0;
+}
+
+_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor(registers, sThisAddressSpace);
+ cursor.setInfoBasedOnIPRegister();
+
+ // Walk each frame.
+ while (true) {
+
+ // Ask libuwind to get next frame (skip over first frame which is
+ // _Unwind_Backtrace()).
+ if (cursor.step() != UNW_STEP_SUCCESS)
+ return _URC_END_OF_STACK;
+
+ // Call trace function with this frame.
+ _Unwind_Reason_Code result =
+ (*callback)((struct _Unwind_Context *)(&cursor), ref);
+ if (result != _URC_NO_REASON)
+ return result;
+ }
+}
+
+uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ return cursor->getSP();
+}
+
+void *_Unwind_FindEnclosingFunction(void *pc) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor(registers, sThisAddressSpace);
+
+ unw_proc_info_t info;
+ cursor.setIP((uintptr_t)pc);
+ cursor.setInfoBasedOnIPRegister();
+
+ cursor.getInfo(&info);
+ return info.end_ip ? (void *)info.start_ip : NULL;
+}
+
+void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases) {
+ NativeUnwindRegisters registers;
+ ThisUnwindCursor cursor(registers, sThisAddressSpace);
+
+ unw_proc_info_t info;
+ cursor.setIP((uintptr_t)pc);
+ cursor.setInfoBasedOnIPRegister();
+
+ cursor.getInfo(&info);
+ if (info.end_ip == 0)
+ return NULL;
+ bases->tbase = 0; /* Not supported */
+ bases->dbase = (void *)info.data_base;
+ bases->func = (void *)info.start_ip;
+ return (void *)info.unwind_info;
+}
+
+uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) {
+ ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
+ unw_proc_info_t frameInfo;
+ cursor->getInfo(&frameInfo);
+ return frameInfo.data_base;
+}
+
+uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { return 0; }
+
+void __register_frame(const void *fde) {
+ MyCFIParser::pint_t pcStart, pcEnd;
+
+ MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
+ if (pcEnd == 0)
+ return; // Bad FDE.
+
+ sThisAddressSpace.addFDE(pcStart, pcEnd, (uintptr_t)fde);
+}
+
+void __register_frame_info(const void *ehframe, void *storage) {
+#if 0
+ // Temporarily disabled due to init startup ordering issue:
+ // __register_frame_info gets called before __do_global_ctors_aux and so
+ // sThisAddressSpace has not yet been initialized.
+ sThisAddressSpace.setLazyReload();
+#endif
+}
+
+void __deregister_frame(const void *fde) {
+ MyCFIParser::pint_t pcStart, pcEnd;
+
+ MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
+ if (pcEnd == 0)
+ return; // Bad FDE.
+
+ sThisAddressSpace.removeFDE(pcStart, pcEnd, (uintptr_t)fde);
+}
+
+void *__deregister_frame_info(const void *ehFrameStart) {
+ sThisAddressSpace.removeDSO((LocalAddressSpace::pint_t)ehFrameStart);
+ return NULL;
+}
Index: contrib/netbsd-unwind/rb.c
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/rb.c
@@ -0,0 +1,1318 @@
+/* $NetBSD: rb.c,v 1.13 2014/08/22 17:19:48 matt Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <sys/types.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdbool.h>
+#ifdef RBDEBUG
+#define KASSERT(s) assert(s)
+#else
+#define KASSERT(s) do { } while (/*CONSTCOND*/ 0)
+#endif
+__RCSID("$NetBSD: rb.c,v 1.13 2014/08/22 17:19:48 matt Exp $");
+#else
+#include <lib/libkern/libkern.h>
+__KERNEL_RCSID(0, "$NetBSD: rb.c,v 1.13 2014/08/22 17:19:48 matt Exp $");
+#endif
+
+#include "rbtree.h"
+
+static void rb_tree_insert_rebalance(struct rb_tree *, struct rb_node *);
+static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *,
+ unsigned int);
+#ifdef RBDEBUG
+static const struct rb_node *rb_tree_iterate_const(const struct rb_tree *,
+ const struct rb_node *, const unsigned int);
+static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *,
+ const struct rb_node *, bool);
+#else
+#define rb_tree_check_node(a, b, c, d) true
+#endif
+
+#define RB_NODETOITEM(rbto, rbn) \
+ ((void *)((uintptr_t)(rbn) - (rbto)->rbto_node_offset))
+#define RB_ITEMTONODE(rbto, rbn) \
+ ((rb_node_t *)((uintptr_t)(rbn) + (rbto)->rbto_node_offset))
+
+#define RB_SENTINEL_NODE NULL
+
+void
+__rb_tree_init(struct rb_tree *rbt, const rb_tree_ops_t *ops)
+{
+
+ rbt->rbt_ops = ops;
+ rbt->rbt_root = RB_SENTINEL_NODE;
+ RB_TAILQ_INIT(&rbt->rbt_nodes);
+#ifndef RBSMALL
+ rbt->rbt_minmax[RB_DIR_LEFT] = rbt->rbt_root; /* minimum node */
+ rbt->rbt_minmax[RB_DIR_RIGHT] = rbt->rbt_root; /* maximum node */
+#endif
+#ifdef RBSTATS
+ rbt->rbt_count = 0;
+ rbt->rbt_insertions = 0;
+ rbt->rbt_removals = 0;
+ rbt->rbt_insertion_rebalance_calls = 0;
+ rbt->rbt_insertion_rebalance_passes = 0;
+ rbt->rbt_removal_rebalance_calls = 0;
+ rbt->rbt_removal_rebalance_passes = 0;
+#endif
+}
+
+void *
+__rb_tree_find_node(struct rb_tree *rbt, const void *key)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root;
+
+ while (!RB_SENTINEL_P(parent)) {
+ void *pobj = RB_NODETOITEM(rbto, parent);
+ const signed int diff = (*compare_key)(rbto->rbto_context,
+ pobj, key);
+ if (diff == 0)
+ return pobj;
+ parent = parent->rb_nodes[diff < 0];
+ }
+
+ return NULL;
+}
+
+void *
+__rb_tree_find_node_geq(struct rb_tree *rbt, const void *key)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root, *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ void *pobj = RB_NODETOITEM(rbto, parent);
+ const signed int diff = (*compare_key)(rbto->rbto_context,
+ pobj, key);
+ if (diff == 0)
+ return pobj;
+ if (diff > 0)
+ last = parent;
+ parent = parent->rb_nodes[diff < 0];
+ }
+
+ return last == NULL ? NULL : RB_NODETOITEM(rbto, last);
+}
+
+void *
+__rb_tree_find_node_leq(struct rb_tree *rbt, const void *key)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ rbto_compare_key_fn compare_key = rbto->rbto_compare_key;
+ struct rb_node *parent = rbt->rbt_root, *last = NULL;
+
+ while (!RB_SENTINEL_P(parent)) {
+ void *pobj = RB_NODETOITEM(rbto, parent);
+ const signed int diff = (*compare_key)(rbto->rbto_context,
+ pobj, key);
+ if (diff == 0)
+ return pobj;
+ if (diff < 0)
+ last = parent;
+ parent = parent->rb_nodes[diff < 0];
+ }
+
+ return last == NULL ? NULL : RB_NODETOITEM(rbto, last);
+}
+
+void *
+__rb_tree_insert_node(struct rb_tree *rbt, void *object)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes;
+ struct rb_node *parent, *tmp, *self = RB_ITEMTONODE(rbto, object);
+ unsigned int position;
+ bool rebalance;
+
+ RBSTAT_INC(rbt->rbt_insertions);
+
+ tmp = rbt->rbt_root;
+ /*
+ * This is a hack. Because rbt->rbt_root is just a struct rb_node *,
+ * just like rb_node->rb_nodes[RB_DIR_LEFT], we can use this fact to
+ * avoid a lot of tests for root and know that even at root,
+ * updating RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
+ * update rbt->rbt_root.
+ */
+ parent = (struct rb_node *)(void *)&rbt->rbt_root;
+ position = RB_DIR_LEFT;
+
+ /*
+ * Find out where to place this new leaf.
+ */
+ while (!RB_SENTINEL_P(tmp)) {
+ void *tobj = RB_NODETOITEM(rbto, tmp);
+ const signed int diff = (*compare_nodes)(rbto->rbto_context,
+ tobj, object);
+ if (__predict_false(diff == 0)) {
+ /*
+ * Node already exists; return it.
+ */
+ return tobj;
+ }
+ parent = tmp;
+ position = (diff < 0);
+ tmp = parent->rb_nodes[position];
+ }
+
+#ifdef RBDEBUG
+ {
+ struct rb_node *prev = NULL, *next = NULL;
+
+ if (position == RB_DIR_RIGHT)
+ prev = parent;
+ else if (tmp != rbt->rbt_root)
+ next = parent;
+
+ /*
+ * Verify our sequential position
+ */
+ KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
+ KASSERT(next == NULL || !RB_SENTINEL_P(next));
+ if (prev != NULL && next == NULL)
+ next = TAILQ_NEXT(prev, rb_link);
+ if (prev == NULL && next != NULL)
+ prev = TAILQ_PREV(next, rb_node_qh, rb_link);
+ KASSERT(prev == NULL || !RB_SENTINEL_P(prev));
+ KASSERT(next == NULL || !RB_SENTINEL_P(next));
+ KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0);
+ KASSERT(next == NULL || (*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, self), RB_NODETOITEM(rbto, next)) < 0);
+ }
+#endif
+
+ /*
+ * Initialize the node and insert as a leaf into the tree.
+ */
+ RB_SET_FATHER(self, parent);
+ RB_SET_POSITION(self, position);
+ if (__predict_false(parent == (struct rb_node *)(void *)&rbt->rbt_root)) {
+ RB_MARK_BLACK(self); /* root is always black */
+#ifndef RBSMALL
+ rbt->rbt_minmax[RB_DIR_LEFT] = self;
+ rbt->rbt_minmax[RB_DIR_RIGHT] = self;
+#endif
+ rebalance = false;
+ } else {
+ KASSERT(position == RB_DIR_LEFT || position == RB_DIR_RIGHT);
+#ifndef RBSMALL
+ /*
+ * Keep track of the minimum and maximum nodes. If our
+ * parent is a minmax node and we on their min/max side,
+ * we must be the new min/max node.
+ */
+ if (parent == rbt->rbt_minmax[position])
+ rbt->rbt_minmax[position] = self;
+#endif /* !RBSMALL */
+ /*
+ * All new nodes are colored red. We only need to rebalance
+ * if our parent is also red.
+ */
+ RB_MARK_RED(self);
+ rebalance = RB_RED_P(parent);
+ }
+ KASSERT(RB_SENTINEL_P(parent->rb_nodes[position]));
+ self->rb_left = parent->rb_nodes[position];
+ self->rb_right = parent->rb_nodes[position];
+ parent->rb_nodes[position] = self;
+ KASSERT(RB_CHILDLESS_P(self));
+
+ /*
+ * Insert the new node into a sorted list for easy sequential access
+ */
+ RBSTAT_INC(rbt->rbt_count);
+#ifdef RBDEBUG
+ if (RB_ROOT_P(rbt, self)) {
+ RB_TAILQ_INSERT_HEAD(&rbt->rbt_nodes, self, rb_link);
+ } else if (position == RB_DIR_LEFT) {
+ KASSERT((*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, self),
+ RB_NODETOITEM(rbto, RB_FATHER(self))) < 0);
+ RB_TAILQ_INSERT_BEFORE(RB_FATHER(self), self, rb_link);
+ } else {
+ KASSERT((*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, RB_FATHER(self)),
+ RB_NODETOITEM(rbto, self)) < 0);
+ RB_TAILQ_INSERT_AFTER(&rbt->rbt_nodes, RB_FATHER(self),
+ self, rb_link);
+ }
+#endif
+ KASSERT(rb_tree_check_node(rbt, self, NULL, !rebalance));
+
+ /*
+ * Rebalance tree after insertion
+ */
+ if (rebalance) {
+ rb_tree_insert_rebalance(rbt, self);
+ KASSERT(rb_tree_check_node(rbt, self, NULL, true));
+ }
+
+ /* Succesfully inserted, return our node pointer. */
+ return object;
+}
+
+/*
+ * Swap the location and colors of 'self' and its child @ which. The child
+ * can not be a sentinel node. This is our rotation function. However,
+ * since it preserves coloring, it great simplifies both insertion and
+ * removal since rotation almost always involves the exchanging of colors
+ * as a separate step.
+ */
+/*ARGSUSED*/
+static void
+rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father,
+ const unsigned int which)
+{
+ const unsigned int other = which ^ RB_DIR_OTHER;
+ struct rb_node * const grandpa = RB_FATHER(old_father);
+ struct rb_node * const old_child = old_father->rb_nodes[which];
+ struct rb_node * const new_father = old_child;
+ struct rb_node * const new_child = old_father;
+
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+
+ KASSERT(!RB_SENTINEL_P(old_child));
+ KASSERT(RB_FATHER(old_child) == old_father);
+
+ KASSERT(rb_tree_check_node(rbt, old_father, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, old_child, NULL, false));
+ KASSERT(RB_ROOT_P(rbt, old_father) ||
+ rb_tree_check_node(rbt, grandpa, NULL, false));
+
+ /*
+ * Exchange descendant linkages.
+ */
+ grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
+ new_child->rb_nodes[which] = old_child->rb_nodes[other];
+ new_father->rb_nodes[other] = new_child;
+
+ /*
+ * Update ancestor linkages
+ */
+ RB_SET_FATHER(new_father, grandpa);
+ RB_SET_FATHER(new_child, new_father);
+
+ /*
+ * Exchange properties between new_father and new_child. The only
+ * change is that new_child's position is now on the other side.
+ */
+#if 0
+ {
+ struct rb_node tmp;
+ tmp.rb_info = 0;
+ RB_COPY_PROPERTIES(&tmp, old_child);
+ RB_COPY_PROPERTIES(new_father, old_father);
+ RB_COPY_PROPERTIES(new_child, &tmp);
+ }
+#else
+ RB_SWAP_PROPERTIES(new_father, new_child);
+#endif
+ RB_SET_POSITION(new_child, other);
+
+ /*
+ * Make sure to reparent the new child to ourself.
+ */
+ if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
+ RB_SET_FATHER(new_child->rb_nodes[which], new_child);
+ RB_SET_POSITION(new_child->rb_nodes[which], which);
+ }
+
+ KASSERT(rb_tree_check_node(rbt, new_father, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, new_child, NULL, false));
+ KASSERT(RB_ROOT_P(rbt, new_father) ||
+ rb_tree_check_node(rbt, grandpa, NULL, false));
+}
+
+static void
+rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self)
+{
+ struct rb_node * father = RB_FATHER(self);
+ struct rb_node * grandpa = RB_FATHER(father);
+ struct rb_node * uncle;
+ unsigned int which;
+ unsigned int other;
+
+ KASSERT(!RB_ROOT_P(rbt, self));
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ RBSTAT_INC(rbt->rbt_insertion_rebalance_calls);
+
+ for (;;) {
+ KASSERT(!RB_SENTINEL_P(self));
+
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ /*
+ * We are red and our parent is red, therefore we must have a
+ * grandfather and he must be black.
+ */
+ grandpa = RB_FATHER(father);
+ KASSERT(RB_BLACK_P(grandpa));
+ KASSERT(RB_DIR_RIGHT == 1 && RB_DIR_LEFT == 0);
+ which = (father == grandpa->rb_right);
+ other = which ^ RB_DIR_OTHER;
+ uncle = grandpa->rb_nodes[other];
+
+ if (RB_BLACK_P(uncle))
+ break;
+
+ RBSTAT_INC(rbt->rbt_insertion_rebalance_passes);
+ /*
+ * Case 1: our uncle is red
+ * Simply invert the colors of our parent and
+ * uncle and make our grandparent red. And
+ * then solve the problem up at his level.
+ */
+ RB_MARK_BLACK(uncle);
+ RB_MARK_BLACK(father);
+ if (__predict_false(RB_ROOT_P(rbt, grandpa))) {
+ /*
+ * If our grandpa is root, don't bother
+ * setting him to red, just return.
+ */
+ KASSERT(RB_BLACK_P(grandpa));
+ return;
+ }
+ RB_MARK_RED(grandpa);
+ self = grandpa;
+ father = RB_FATHER(self);
+ KASSERT(RB_RED_P(self));
+ if (RB_BLACK_P(father)) {
+ /*
+ * If our greatgrandpa is black, we're done.
+ */
+ KASSERT(RB_BLACK_P(rbt->rbt_root));
+ return;
+ }
+ }
+
+ KASSERT(!RB_ROOT_P(rbt, self));
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_RED_P(father));
+ KASSERT(RB_BLACK_P(uncle));
+ KASSERT(RB_BLACK_P(grandpa));
+ /*
+ * Case 2&3: our uncle is black.
+ */
+ if (self == father->rb_nodes[other]) {
+ /*
+ * Case 2: we are on the same side as our uncle
+ * Swap ourselves with our parent so this case
+ * becomes case 3. Basically our parent becomes our
+ * child.
+ */
+ rb_tree_reparent_nodes(rbt, father, other);
+ KASSERT(RB_FATHER(father) == self);
+ KASSERT(self->rb_nodes[which] == father);
+ KASSERT(RB_FATHER(self) == grandpa);
+ self = father;
+ father = RB_FATHER(self);
+ }
+ KASSERT(RB_RED_P(self) && RB_RED_P(father));
+ KASSERT(grandpa->rb_nodes[which] == father);
+ /*
+ * Case 3: we are opposite a child of a black uncle.
+ * Swap our parent and grandparent. Since our grandfather
+ * is black, our father will become black and our new sibling
+ * (former grandparent) will become red.
+ */
+ rb_tree_reparent_nodes(rbt, grandpa, which);
+ KASSERT(RB_FATHER(self) == father);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER] == grandpa);
+ KASSERT(RB_RED_P(self));
+ KASSERT(RB_BLACK_P(father));
+ KASSERT(RB_RED_P(grandpa));
+
+ /*
+ * Final step: Set the root to black.
+ */
+ RB_MARK_BLACK(rbt->rbt_root);
+}
+
+static void
+rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance)
+{
+ const unsigned int which = RB_POSITION(self);
+ struct rb_node *father = RB_FATHER(self);
+#ifndef RBSMALL
+ const bool was_root = RB_ROOT_P(rbt, self);
+#endif
+
+ KASSERT(rebalance || (RB_ROOT_P(rbt, self) || RB_RED_P(self)));
+ KASSERT(!rebalance || RB_BLACK_P(self));
+ KASSERT(RB_CHILDLESS_P(self));
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+
+ /*
+ * Since we are childless, we know that self->rb_left is pointing
+ * to the sentinel node.
+ */
+ father->rb_nodes[which] = self->rb_left;
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update min/max.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ RBSTAT_DEC(rbt->rbt_count);
+#ifndef RBSMALL
+ if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self)) {
+ rbt->rbt_minmax[RB_POSITION(self)] = father;
+ /*
+ * When removing the root, rbt->rbt_minmax[RB_DIR_LEFT] is
+ * updated automatically, but we also need to update
+ * rbt->rbt_minmax[RB_DIR_RIGHT];
+ */
+ if (__predict_false(was_root)) {
+ rbt->rbt_minmax[RB_DIR_RIGHT] = father;
+ }
+ }
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ /*
+ * Rebalance if requested.
+ */
+ if (rebalance)
+ rb_tree_removal_rebalance(rbt, father, which);
+ KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
+}
+
+/*
+ * When deleting an interior node
+ */
+static void
+rb_tree_swap_prune_and_rebalance(struct rb_tree *rbt, struct rb_node *self,
+ struct rb_node *standin)
+{
+ const unsigned int standin_which = RB_POSITION(standin);
+ unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
+ struct rb_node *standin_son;
+ struct rb_node *standin_father = RB_FATHER(standin);
+ bool rebalance = RB_BLACK_P(standin);
+
+ if (standin_father == self) {
+ /*
+ * As a child of self, any childen would be opposite of
+ * our parent.
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
+ standin_son = standin->rb_nodes[standin_which];
+ } else {
+ /*
+ * Since we aren't a child of self, any childen would be
+ * on the same side as our parent.
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_which]));
+ standin_son = standin->rb_nodes[standin_other];
+ }
+
+ /*
+ * the node we are removing must have two children.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self));
+ /*
+ * If standin has a child, it must be red.
+ */
+ KASSERT(RB_SENTINEL_P(standin_son) || RB_RED_P(standin_son));
+
+ /*
+ * Verify things are sane.
+ */
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
+
+ if (__predict_false(RB_RED_P(standin_son))) {
+ /*
+ * We know we have a red child so if we flip it to black
+ * we don't have to rebalance.
+ */
+ KASSERT(rb_tree_check_node(rbt, standin_son, NULL, true));
+ RB_MARK_BLACK(standin_son);
+ rebalance = false;
+
+ if (standin_father == self) {
+ KASSERT(RB_POSITION(standin_son) == standin_which);
+ } else {
+ KASSERT(RB_POSITION(standin_son) == standin_other);
+ /*
+ * Change the son's parentage to point to his grandpa.
+ */
+ RB_SET_FATHER(standin_son, standin_father);
+ RB_SET_POSITION(standin_son, standin_which);
+ }
+ }
+
+ if (standin_father == self) {
+ /*
+ * If we are about to delete the standin's father, then when
+ * we call rebalance, we need to use ourselves as our father.
+ * Otherwise remember our original father. Also, sincef we are
+ * our standin's father we only need to reparent the standin's
+ * brother.
+ *
+ * | R --> S |
+ * | Q S --> Q T |
+ * | t --> |
+ */
+ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other]));
+ KASSERT(!RB_SENTINEL_P(self->rb_nodes[standin_other]));
+ KASSERT(self->rb_nodes[standin_which] == standin);
+ /*
+ * Have our son/standin adopt his brother as his new son.
+ */
+ standin_father = standin;
+ } else {
+ /*
+ * | R --> S . |
+ * | / \ | T --> / \ | / |
+ * | ..... | S --> ..... | T |
+ *
+ * Sever standin's connection to his father.
+ */
+ standin_father->rb_nodes[standin_which] = standin_son;
+ /*
+ * Adopt the far son.
+ */
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+ KASSERT(RB_POSITION(self->rb_nodes[standin_other]) == standin_other);
+ /*
+ * Use standin_other because we need to preserve standin_which
+ * for the removal_rebalance.
+ */
+ standin_other = standin_which;
+ }
+
+ /*
+ * Move the only remaining son to our standin. If our standin is our
+ * son, this will be the only son needed to be moved.
+ */
+ KASSERT(standin->rb_nodes[standin_other] != self->rb_nodes[standin_other]);
+ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
+ RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
+
+ /*
+ * Now copy the result of self to standin and then replace
+ * self with standin in the tree.
+ */
+ RB_COPY_PROPERTIES(standin, self);
+ RB_SET_FATHER(standin, RB_FATHER(self));
+ RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update min/max.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ RBSTAT_DEC(rbt->rbt_count);
+#ifndef RBSMALL
+ if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self))
+ rbt->rbt_minmax[RB_POSITION(self)] = RB_FATHER(self);
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, false));
+ KASSERT(RB_FATHER_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin_father, NULL, false));
+ KASSERT(RB_LEFT_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin->rb_left, NULL, false));
+ KASSERT(RB_RIGHT_SENTINEL_P(standin)
+ || rb_tree_check_node(rbt, standin->rb_right, NULL, false));
+
+ if (!rebalance)
+ return;
+
+ rb_tree_removal_rebalance(rbt, standin_father, standin_which);
+ KASSERT(rb_tree_check_node(rbt, standin, NULL, true));
+}
+
+/*
+ * We could do this by doing
+ * rb_tree_node_swap(rbt, self, which);
+ * rb_tree_prune_node(rbt, self, false);
+ *
+ * But it's more efficient to just evalate and recolor the child.
+ */
+static void
+rb_tree_prune_blackred_branch(struct rb_tree *rbt, struct rb_node *self,
+ unsigned int which)
+{
+ struct rb_node *father = RB_FATHER(self);
+ struct rb_node *son = self->rb_nodes[which];
+#ifndef RBSMALL
+ const bool was_root = RB_ROOT_P(rbt, self);
+#endif
+
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+ KASSERT(RB_BLACK_P(self) && RB_RED_P(son));
+ KASSERT(!RB_TWOCHILDREN_P(son));
+ KASSERT(RB_CHILDLESS_P(son));
+ KASSERT(rb_tree_check_node(rbt, self, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, son, NULL, false));
+
+ /*
+ * Remove ourselves from the tree and give our former child our
+ * properties (position, color, root).
+ */
+ RB_COPY_PROPERTIES(son, self);
+ father->rb_nodes[RB_POSITION(son)] = son;
+ RB_SET_FATHER(son, father);
+
+ /*
+ * Remove ourselves from the node list, decrement the count,
+ * and update minmax.
+ */
+ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link);
+ RBSTAT_DEC(rbt->rbt_count);
+#ifndef RBSMALL
+ if (__predict_false(was_root)) {
+ KASSERT(rbt->rbt_minmax[which] == son);
+ rbt->rbt_minmax[which ^ RB_DIR_OTHER] = son;
+ } else if (rbt->rbt_minmax[RB_POSITION(self)] == self) {
+ rbt->rbt_minmax[RB_POSITION(self)] = son;
+ }
+ RB_SET_FATHER(self, NULL);
+#endif
+
+ KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true));
+ KASSERT(rb_tree_check_node(rbt, son, NULL, true));
+}
+
+void
+__rb_tree_remove_node(struct rb_tree *rbt, void *object)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ struct rb_node *standin, *self = RB_ITEMTONODE(rbto, object);
+ unsigned int which;
+
+ KASSERT(!RB_SENTINEL_P(self));
+ RBSTAT_INC(rbt->rbt_removals);
+
+ /*
+ * In the following diagrams, we (the node to be removed) are S. Red
+ * nodes are lowercase. T could be either red or black.
+ *
+ * Remember the major axiom of the red-black tree: the number of
+ * black nodes from the root to each leaf is constant across all
+ * leaves, only the number of red nodes varies.
+ *
+ * Thus removing a red leaf doesn't require any other changes to a
+ * red-black tree. So if we must remove a node, attempt to rearrange
+ * the tree so we can remove a red node.
+ *
+ * The simpliest case is a childless red node or a childless root node:
+ *
+ * | T --> T | or | R --> * |
+ * | s --> * |
+ */
+ if (RB_CHILDLESS_P(self)) {
+ const bool rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
+ rb_tree_prune_node(rbt, self, rebalance);
+ return;
+ }
+ KASSERT(!RB_CHILDLESS_P(self));
+ if (!RB_TWOCHILDREN_P(self)) {
+ /*
+ * The next simpliest case is the node we are deleting is
+ * black and has one red child.
+ *
+ * | T --> T --> T |
+ * | S --> R --> R |
+ * | r --> s --> * |
+ */
+ which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
+ KASSERT(RB_BLACK_P(self));
+ KASSERT(RB_RED_P(self->rb_nodes[which]));
+ KASSERT(RB_CHILDLESS_P(self->rb_nodes[which]));
+ rb_tree_prune_blackred_branch(rbt, self, which);
+ return;
+ }
+ KASSERT(RB_TWOCHILDREN_P(self));
+
+ /*
+ * We invert these because we prefer to remove from the inside of
+ * the tree.
+ */
+ which = RB_POSITION(self) ^ RB_DIR_OTHER;
+
+ /*
+ * Let's find the node closes to us opposite of our parent
+ * Now swap it with ourself, "prune" it, and rebalance, if needed.
+ */
+ standin = RB_ITEMTONODE(rbto, __rb_tree_iterate(rbt, object, which));
+ rb_tree_swap_prune_and_rebalance(rbt, self, standin);
+}
+
+static void
+rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent,
+ unsigned int which)
+{
+ KASSERT(!RB_SENTINEL_P(parent));
+ KASSERT(RB_SENTINEL_P(parent->rb_nodes[which]));
+ KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT);
+ RBSTAT_INC(rbt->rbt_removal_rebalance_calls);
+
+ while (RB_BLACK_P(parent->rb_nodes[which])) {
+ unsigned int other = which ^ RB_DIR_OTHER;
+ struct rb_node *brother = parent->rb_nodes[other];
+
+ RBSTAT_INC(rbt->rbt_removal_rebalance_passes);
+
+ KASSERT(!RB_SENTINEL_P(brother));
+ /*
+ * For cases 1, 2a, and 2b, our brother's children must
+ * be black and our father must be black
+ */
+ if (RB_BLACK_P(parent)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)) {
+ if (RB_RED_P(brother)) {
+ /*
+ * Case 1: Our brother is red, swap its
+ * position (and colors) with our parent.
+ * This should now be case 2b (unless C or E
+ * has a red child which is case 3; thus no
+ * explicit branch to case 2b).
+ *
+ * B -> D
+ * A d -> b E
+ * C E -> A C
+ */
+ KASSERT(RB_BLACK_P(parent));
+ rb_tree_reparent_nodes(rbt, parent, other);
+ brother = parent->rb_nodes[other];
+ KASSERT(!RB_SENTINEL_P(brother));
+ KASSERT(RB_RED_P(parent));
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
+ } else {
+ /*
+ * Both our parent and brother are black.
+ * Change our brother to red, advance up rank
+ * and go through the loop again.
+ *
+ * B -> *B
+ * *A D -> A d
+ * C E -> C E
+ */
+ RB_MARK_RED(brother);
+ KASSERT(RB_BLACK_P(brother->rb_left));
+ KASSERT(RB_BLACK_P(brother->rb_right));
+ if (RB_ROOT_P(rbt, parent))
+ return; /* root == parent == black */
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, false));
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, false));
+ which = RB_POSITION(parent);
+ parent = RB_FATHER(parent);
+ continue;
+ }
+ }
+ /*
+ * Avoid an else here so that case 2a above can hit either
+ * case 2b, 3, or 4.
+ */
+ if (RB_RED_P(parent)
+ && RB_BLACK_P(brother)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)) {
+ KASSERT(RB_RED_P(parent));
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_BLACK_P(brother->rb_left));
+ KASSERT(RB_BLACK_P(brother->rb_right));
+ /*
+ * We are black, our father is red, our brother and
+ * both nephews are black. Simply invert/exchange the
+ * colors of our father and brother (to black and red
+ * respectively).
+ *
+ * | f --> F |
+ * | * B --> * b |
+ * | N N --> N N |
+ */
+ RB_MARK_BLACK(parent);
+ RB_MARK_RED(brother);
+ KASSERT(rb_tree_check_node(rbt, brother, NULL, true));
+ break; /* We're done! */
+ } else {
+ /*
+ * Our brother must be black and have at least one
+ * red child (it may have two).
+ */
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_RED_P(brother->rb_nodes[which]) ||
+ RB_RED_P(brother->rb_nodes[other]));
+ if (RB_BLACK_P(brother->rb_nodes[other])) {
+ /*
+ * Case 3: our brother is black, our near
+ * nephew is red, and our far nephew is black.
+ * Swap our brother with our near nephew.
+ * This result in a tree that matches case 4.
+ * (Our father could be red or black).
+ *
+ * | F --> F |
+ * | x B --> x B |
+ * | n --> n |
+ */
+ KASSERT(RB_RED_P(brother->rb_nodes[which]));
+ rb_tree_reparent_nodes(rbt, brother, which);
+ KASSERT(RB_FATHER(brother) == parent->rb_nodes[other]);
+ brother = parent->rb_nodes[other];
+ KASSERT(RB_RED_P(brother->rb_nodes[other]));
+ }
+ /*
+ * Case 4: our brother is black and our far nephew
+ * is red. Swap our father and brother locations and
+ * change our far nephew to black. (these can be
+ * done in either order so we change the color first).
+ * The result is a valid red-black tree and is a
+ * terminal case. (again we don't care about the
+ * father's color)
+ *
+ * If the father is red, we will get a red-black-black
+ * tree:
+ * | f -> f --> b |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If the father is black, we will get an all black
+ * tree:
+ * | F -> F --> B |
+ * | B -> B --> F N |
+ * | n -> N --> |
+ *
+ * If we had two red nephews, then after the swap,
+ * our former father would have a red grandson.
+ */
+ KASSERT(RB_BLACK_P(brother));
+ KASSERT(RB_RED_P(brother->rb_nodes[other]));
+ RB_MARK_BLACK(brother->rb_nodes[other]);
+ rb_tree_reparent_nodes(rbt, parent, other);
+ break; /* We're done! */
+ }
+ }
+ KASSERT(rb_tree_check_node(rbt, parent, NULL, true));
+}
+
+void *
+__rb_tree_iterate(struct rb_tree *rbt, void *object,
+ const unsigned int direction)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ const unsigned int other = direction ^ RB_DIR_OTHER;
+ struct rb_node *self;
+
+ KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
+
+ if (object == NULL) {
+#ifndef RBSMALL
+ if (RB_SENTINEL_P(rbt->rbt_root))
+ return NULL;
+ return RB_NODETOITEM(rbto, rbt->rbt_minmax[direction]);
+#else
+ self = rbt->rbt_root;
+ if (RB_SENTINEL_P(self))
+ return NULL;
+ while (!RB_SENTINEL_P(self->rb_nodes[direction]))
+ self = self->rb_nodes[direction];
+ return RB_NODETOITEM(rbto, self);
+#endif /* !RBSMALL */
+ }
+ self = RB_ITEMTONODE(rbto, object);
+ KASSERT(!RB_SENTINEL_P(self));
+ /*
+ * We can't go any further in this direction. We proceed up in the
+ * opposite direction until our parent is in direction we want to go.
+ */
+ if (RB_SENTINEL_P(self->rb_nodes[direction])) {
+ while (!RB_ROOT_P(rbt, self)) {
+ if (other == RB_POSITION(self))
+ return RB_NODETOITEM(rbto, RB_FATHER(self));
+ self = RB_FATHER(self);
+ }
+ return NULL;
+ }
+
+ /*
+ * Advance down one in current direction and go down as far as possible
+ * in the opposite direction.
+ */
+ self = self->rb_nodes[direction];
+ KASSERT(!RB_SENTINEL_P(self));
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return RB_NODETOITEM(rbto, self);
+}
+
+#ifdef RBDEBUG
+static const struct rb_node *
+rb_tree_iterate_const(const struct rb_tree *rbt, const struct rb_node *self,
+ const unsigned int direction)
+{
+ const unsigned int other = direction ^ RB_DIR_OTHER;
+ KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT);
+
+ if (self == NULL) {
+#ifndef RBSMALL
+ if (RB_SENTINEL_P(rbt->rbt_root))
+ return NULL;
+ return rbt->rbt_minmax[direction];
+#else
+ self = rbt->rbt_root;
+ if (RB_SENTINEL_P(self))
+ return NULL;
+ while (!RB_SENTINEL_P(self->rb_nodes[direction]))
+ self = self->rb_nodes[direction];
+ return self;
+#endif /* !RBSMALL */
+ }
+ KASSERT(!RB_SENTINEL_P(self));
+ /*
+ * We can't go any further in this direction. We proceed up in the
+ * opposite direction until our parent is in direction we want to go.
+ */
+ if (RB_SENTINEL_P(self->rb_nodes[direction])) {
+ while (!RB_ROOT_P(rbt, self)) {
+ if (other == RB_POSITION(self))
+ return RB_FATHER(self);
+ self = RB_FATHER(self);
+ }
+ return NULL;
+ }
+
+ /*
+ * Advance down one in current direction and go down as far as possible
+ * in the opposite direction.
+ */
+ self = self->rb_nodes[direction];
+ KASSERT(!RB_SENTINEL_P(self));
+ while (!RB_SENTINEL_P(self->rb_nodes[other]))
+ self = self->rb_nodes[other];
+ return self;
+}
+
+static unsigned int
+rb_tree_count_black(const struct rb_node *self)
+{
+ unsigned int left, right;
+
+ if (RB_SENTINEL_P(self))
+ return 0;
+
+ left = rb_tree_count_black(self->rb_left);
+ right = rb_tree_count_black(self->rb_right);
+
+ KASSERT(left == right);
+
+ return left + RB_BLACK_P(self);
+}
+
+static bool
+rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self,
+ const struct rb_node *prev, bool red_check)
+{
+ const rb_tree_ops_t *rbto = rbt->rbt_ops;
+ rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes;
+
+ KASSERT(!RB_SENTINEL_P(self));
+ KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0);
+
+ /*
+ * Verify our relationship to our parent.
+ */
+ if (RB_ROOT_P(rbt, self)) {
+ KASSERT(self == rbt->rbt_root);
+ KASSERT(RB_POSITION(self) == RB_DIR_LEFT);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
+ KASSERT(RB_FATHER(self) == (const struct rb_node *) &rbt->rbt_root);
+ } else {
+ int diff = (*compare_nodes)(rbto->rbto_context,
+ RB_NODETOITEM(rbto, self),
+ RB_NODETOITEM(rbto, RB_FATHER(self)));
+
+ KASSERT(self != rbt->rbt_root);
+ KASSERT(!RB_FATHER_SENTINEL_P(self));
+ if (RB_POSITION(self) == RB_DIR_LEFT) {
+ KASSERT(diff < 0);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self);
+ } else {
+ KASSERT(diff > 0);
+ KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_RIGHT] == self);
+ }
+ }
+
+ /*
+ * Verify our position in the linked list against the tree itself.
+ */
+ {
+ const struct rb_node *prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
+ const struct rb_node *next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
+ KASSERT(prev0 == TAILQ_PREV(self, rb_node_qh, rb_link));
+ KASSERT(next0 == TAILQ_NEXT(self, rb_link));
+#ifndef RBSMALL
+ KASSERT(prev0 != NULL || self == rbt->rbt_minmax[RB_DIR_LEFT]);
+ KASSERT(next0 != NULL || self == rbt->rbt_minmax[RB_DIR_RIGHT]);
+#endif
+ }
+
+ /*
+ * The root must be black.
+ * There can never be two adjacent red nodes.
+ */
+ if (red_check) {
+ KASSERT(!RB_ROOT_P(rbt, self) || RB_BLACK_P(self));
+ (void) rb_tree_count_black(self);
+ if (RB_RED_P(self)) {
+ const struct rb_node *brother;
+ KASSERT(!RB_ROOT_P(rbt, self));
+ brother = RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER];
+ KASSERT(RB_BLACK_P(RB_FATHER(self)));
+ /*
+ * I'm red and have no children, then I must either
+ * have no brother or my brother also be red and
+ * also have no children. (black count == 0)
+ */
+ KASSERT(!RB_CHILDLESS_P(self)
+ || RB_SENTINEL_P(brother)
+ || RB_RED_P(brother)
+ || RB_CHILDLESS_P(brother));
+ /*
+ * If I'm not childless, I must have two children
+ * and they must be both be black.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || (RB_TWOCHILDREN_P(self)
+ && RB_BLACK_P(self->rb_left)
+ && RB_BLACK_P(self->rb_right)));
+ /*
+ * If I'm not childless, thus I have black children,
+ * then my brother must either be black or have two
+ * black children.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || RB_BLACK_P(brother)
+ || (RB_TWOCHILDREN_P(brother)
+ && RB_BLACK_P(brother->rb_left)
+ && RB_BLACK_P(brother->rb_right)));
+ } else {
+ /*
+ * If I'm black and have one child, that child must
+ * be red and childless.
+ */
+ KASSERT(RB_CHILDLESS_P(self)
+ || RB_TWOCHILDREN_P(self)
+ || (!RB_LEFT_SENTINEL_P(self)
+ && RB_RIGHT_SENTINEL_P(self)
+ && RB_RED_P(self->rb_left)
+ && RB_CHILDLESS_P(self->rb_left))
+ || (!RB_RIGHT_SENTINEL_P(self)
+ && RB_LEFT_SENTINEL_P(self)
+ && RB_RED_P(self->rb_right)
+ && RB_CHILDLESS_P(self->rb_right)));
+
+ /*
+ * If I'm a childless black node and my parent is
+ * black, my 2nd closet relative away from my parent
+ * is either red or has a red parent or red children.
+ */
+ if (!RB_ROOT_P(rbt, self)
+ && RB_CHILDLESS_P(self)
+ && RB_BLACK_P(RB_FATHER(self))) {
+ const unsigned int which = RB_POSITION(self);
+ const unsigned int other = which ^ RB_DIR_OTHER;
+ const struct rb_node *relative0, *relative;
+
+ relative0 = rb_tree_iterate_const(rbt,
+ self, other);
+ KASSERT(relative0 != NULL);
+ relative = rb_tree_iterate_const(rbt,
+ relative0, other);
+ KASSERT(relative != NULL);
+ KASSERT(RB_SENTINEL_P(relative->rb_nodes[which]));
+#if 0
+ KASSERT(RB_RED_P(relative)
+ || RB_RED_P(relative->rb_left)
+ || RB_RED_P(relative->rb_right)
+ || RB_RED_P(RB_FATHER(relative)));
+#endif
+ }
+ }
+ /*
+ * A grandparent's children must be real nodes and not
+ * sentinels. First check out grandparent.
+ */
+ KASSERT(RB_ROOT_P(rbt, self)
+ || RB_ROOT_P(rbt, RB_FATHER(self))
+ || RB_TWOCHILDREN_P(RB_FATHER(RB_FATHER(self))));
+ /*
+ * If we are have grandchildren on our left, then
+ * we must have a child on our right.
+ */
+ KASSERT(RB_LEFT_SENTINEL_P(self)
+ || RB_CHILDLESS_P(self->rb_left)
+ || !RB_RIGHT_SENTINEL_P(self));
+ /*
+ * If we are have grandchildren on our right, then
+ * we must have a child on our left.
+ */
+ KASSERT(RB_RIGHT_SENTINEL_P(self)
+ || RB_CHILDLESS_P(self->rb_right)
+ || !RB_LEFT_SENTINEL_P(self));
+
+ /*
+ * If we have a child on the left and it doesn't have two
+ * children make sure we don't have great-great-grandchildren on
+ * the right.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self->rb_left)
+ || RB_CHILDLESS_P(self->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_right)
+ || RB_CHILDLESS_P(self->rb_right->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_right->rb_right->rb_right));
+
+ /*
+ * If we have a child on the right and it doesn't have two
+ * children make sure we don't have great-great-grandchildren on
+ * the left.
+ */
+ KASSERT(RB_TWOCHILDREN_P(self->rb_right)
+ || RB_CHILDLESS_P(self->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_left->rb_right)
+ || RB_CHILDLESS_P(self->rb_left->rb_right->rb_left)
+ || RB_CHILDLESS_P(self->rb_left->rb_right->rb_right));
+
+ /*
+ * If we are fully interior node, then our predecessors and
+ * successors must have no children in our direction.
+ */
+ if (RB_TWOCHILDREN_P(self)) {
+ const struct rb_node *prev0;
+ const struct rb_node *next0;
+
+ prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT);
+ KASSERT(prev0 != NULL);
+ KASSERT(RB_RIGHT_SENTINEL_P(prev0));
+
+ next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT);
+ KASSERT(next0 != NULL);
+ KASSERT(RB_LEFT_SENTINEL_P(next0));
+ }
+ }
+
+ return true;
+}
+
+void
+rb_tree_check(const struct rb_tree *rbt, bool red_check)
+{
+ const struct rb_node *self;
+ const struct rb_node *prev;
+#ifdef RBSTATS
+ unsigned int count = 0;
+#endif
+
+ KASSERT(rbt->rbt_root != NULL);
+ KASSERT(RB_LEFT_P(rbt->rbt_root));
+
+#if defined(RBSTATS) && !defined(RBSMALL)
+ KASSERT(rbt->rbt_count > 1
+ || rbt->rbt_minmax[RB_DIR_LEFT] == rbt->rbt_minmax[RB_DIR_RIGHT]);
+#endif
+
+ prev = NULL;
+ TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
+ rb_tree_check_node(rbt, self, prev, false);
+#ifdef RBSTATS
+ count++;
+#endif
+ }
+#ifdef RBSTATS
+ KASSERT(rbt->rbt_count == count);
+#endif
+ if (red_check) {
+ KASSERT(RB_BLACK_P(rbt->rbt_root));
+ KASSERT(RB_SENTINEL_P(rbt->rbt_root)
+ || rb_tree_count_black(rbt->rbt_root));
+
+ /*
+ * The root must be black.
+ * There can never be two adjacent red nodes.
+ */
+ TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) {
+ rb_tree_check_node(rbt, self, NULL, true);
+ }
+ }
+}
+#endif /* RBDEBUG */
+
+#ifdef RBSTATS
+static void
+rb_tree_mark_depth(const struct rb_tree *rbt, const struct rb_node *self,
+ size_t *depths, size_t depth)
+{
+ if (RB_SENTINEL_P(self))
+ return;
+
+ if (RB_TWOCHILDREN_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
+ rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
+ return;
+ }
+ depths[depth]++;
+ if (!RB_LEFT_SENTINEL_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1);
+ }
+ if (!RB_RIGHT_SENTINEL_P(self)) {
+ rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1);
+ }
+}
+
+void
+rb_tree_depths(const struct rb_tree *rbt, size_t *depths)
+{
+ rb_tree_mark_depth(rbt, rbt->rbt_root, depths, 1);
+}
+#endif /* RBSTATS */
Index: contrib/netbsd-unwind/rbtree.h
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/rbtree.h
@@ -0,0 +1,192 @@
+/* $NetBSD: rbtree.h,v 1.2 2012/02/17 08:20:55 yamt Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_RBTREE_H_
+#define _SYS_RBTREE_H_
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/types.h>
+#else
+#include <stdbool.h>
+#include <inttypes.h>
+#endif
+#include <sys/queue.h>
+#include <sys/endian.h>
+
+__BEGIN_DECLS
+
+typedef struct rb_node {
+ struct rb_node *rb_nodes[2];
+#define RB_DIR_LEFT 0
+#define RB_DIR_RIGHT 1
+#define RB_DIR_OTHER 1
+#define rb_left rb_nodes[RB_DIR_LEFT]
+#define rb_right rb_nodes[RB_DIR_RIGHT]
+
+ /*
+ * rb_info contains the two flags and the parent back pointer.
+ * We put the two flags in the low two bits since we know that
+ * rb_node will have an alignment of 4 or 8 bytes.
+ */
+ uintptr_t rb_info;
+#define RB_FLAG_POSITION 0x2
+#define RB_FLAG_RED 0x1
+#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
+#define RB_FATHER(rb) \
+ ((struct rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
+#define RB_SET_FATHER(rb, father) \
+ ((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
+
+#define RB_SENTINEL_P(rb) ((rb) == NULL)
+#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
+#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
+#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
+#define RB_CHILDLESS_P(rb) \
+ (RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
+#define RB_TWOCHILDREN_P(rb) \
+ (!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
+
+#define RB_POSITION(rb) \
+ (((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
+#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
+#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
+#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
+#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
+#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
+#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
+#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
+#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
+#define RB_SET_POSITION(rb, position) \
+ ((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
+ ((rb)->rb_info &= ~RB_FLAG_POSITION)))
+#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
+#define RB_COPY_PROPERTIES(dst, src) \
+ ((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
+#define RB_SWAP_PROPERTIES(a, b) do { \
+ uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
+ (a)->rb_info ^= xorinfo; \
+ (b)->rb_info ^= xorinfo; \
+ } while (/*CONSTCOND*/ 0)
+#ifdef RBDEBUG
+ TAILQ_ENTRY(rb_node) rb_link;
+#endif
+} rb_node_t;
+
+#define RB_TREE_MIN(T) __rb_tree_iterate((T), NULL, RB_DIR_LEFT)
+#define RB_TREE_MAX(T) __rb_tree_iterate((T), NULL, RB_DIR_RIGHT)
+#define RB_TREE_FOREACH(N, T) \
+ for ((N) = RB_TREE_MIN(T); (N); \
+ (N) = __rb_tree_iterate((T), (N), RB_DIR_RIGHT))
+#define RB_TREE_FOREACH_REVERSE(N, T) \
+ for ((N) = RB_TREE_MAX(T); (N); \
+ (N) = __rb_tree_iterate((T), (N), RB_DIR_LEFT))
+
+#ifdef RBDEBUG
+TAILQ_HEAD(rb_node_qh, rb_node);
+
+#define RB_TAILQ_REMOVE(a, b, c) TAILQ_REMOVE(a, b, c)
+#define RB_TAILQ_INIT(a) TAILQ_INIT(a)
+#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
+#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
+#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
+#else
+#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
+#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
+#endif /* RBDEBUG */
+
+/*
+ * rbto_compare_nodes_fn:
+ * return a positive value if the first node > the second node.
+ * return a negative value if the first node < the second node.
+ * return 0 if they are considered same.
+ *
+ * rbto_compare_key_fn:
+ * return a positive value if the node > the key.
+ * return a negative value if the node < the key.
+ * return 0 if they are considered same.
+ */
+
+typedef signed int (*rbto_compare_nodes_fn)(void *, const void *, const void *);
+typedef signed int (*rbto_compare_key_fn)(void *, const void *, const void *);
+
+typedef struct {
+ rbto_compare_nodes_fn rbto_compare_nodes;
+ rbto_compare_key_fn rbto_compare_key;
+ size_t rbto_node_offset;
+ void *rbto_context;
+} rb_tree_ops_t;
+
+typedef struct rb_tree {
+ struct rb_node *rbt_root;
+ const rb_tree_ops_t *rbt_ops;
+ struct rb_node *rbt_minmax[2];
+#ifdef RBDEBUG
+ struct rb_node_qh rbt_nodes;
+#endif
+#ifdef RBSTATS
+ unsigned int rbt_count;
+ unsigned int rbt_insertions;
+ unsigned int rbt_removals;
+ unsigned int rbt_insertion_rebalance_calls;
+ unsigned int rbt_insertion_rebalance_passes;
+ unsigned int rbt_removal_rebalance_calls;
+ unsigned int rbt_removal_rebalance_passes;
+#endif
+} rb_tree_t;
+
+#ifdef RBSTATS
+#define RBSTAT_INC(v) ((void)((v)++))
+#define RBSTAT_DEC(v) ((void)((v)--))
+#else
+#define RBSTAT_INC(v) do { } while (/*CONSTCOND*/0)
+#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
+#endif
+
+void __rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
+void * __rb_tree_insert_node(rb_tree_t *, void *);
+void * __rb_tree_find_node(rb_tree_t *, const void *);
+void * __rb_tree_find_node_geq(rb_tree_t *, const void *);
+void * __rb_tree_find_node_leq(rb_tree_t *, const void *);
+void __rb_tree_remove_node(rb_tree_t *, void *);
+void * __rb_tree_iterate(rb_tree_t *, void *, const unsigned int);
+#ifdef RBDEBUG
+void rb_tree_check(const rb_tree_t *, bool);
+#endif
+#ifdef RBSTATS
+void rb_tree_depths(const rb_tree_t *, size_t *);
+#endif
+
+__END_DECLS
+
+#endif /* _SYS_RBTREE_H_*/
Index: contrib/netbsd-unwind/unwind.h
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/unwind.h
@@ -0,0 +1,102 @@
+//===------------------------------- unwind.h -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//
+// C++ ABI Level 1 ABI documented at:
+// http://mentorembedded.github.io/cxx-abi/abi-eh.html
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _UNWIND_H
+#define _UNWIND_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef enum {
+ _URC_NO_REASON = 0,
+ _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+ _URC_FATAL_PHASE2_ERROR = 2,
+ _URC_FATAL_PHASE1_ERROR = 3,
+ _URC_NORMAL_STOP = 4,
+ _URC_END_OF_STACK = 5,
+ _URC_HANDLER_FOUND = 6,
+ _URC_INSTALL_CONTEXT = 7,
+ _URC_CONTINUE_UNWIND = 8
+} _Unwind_Reason_Code;
+
+typedef enum {
+ _UA_SEARCH_PHASE = 1,
+ _UA_CLEANUP_PHASE = 2,
+ _UA_HANDLER_FRAME = 4,
+ _UA_FORCE_UNWIND = 8,
+ _UA_END_OF_STACK = 16 /* GCC extension */
+} _Unwind_Action;
+
+struct _Unwind_Context;
+
+struct _Unwind_Exception {
+ uint64_t exception_class;
+ void (*exception_cleanup)(_Unwind_Reason_Code, struct _Unwind_Exception *);
+ uintptr_t private_1;
+ uintptr_t private_2;
+} __attribute__((__aligned__));
+
+typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)(int, _Unwind_Action, uint64_t,
+ struct _Unwind_Exception *,
+ struct _Unwind_Context *,
+ void *);
+
+typedef _Unwind_Reason_Code (*__personality_routine)(int, _Unwind_Action,
+ uint64_t,
+ struct _Unwind_Exception *,
+ struct _Unwind_Context *);
+
+#ifdef _UNWIND_GCC_EXTENSIONS
+struct dwarf_eh_bases {
+ void *tbase;
+ void *dbase;
+ void *func;
+};
+#endif
+
+__BEGIN_DECLS
+
+_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *);
+void _Unwind_Resume(struct _Unwind_Exception *) __dead2;
+_Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *);
+_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *,
+ _Unwind_Stop_Fn, void *);
+void _Unwind_DeleteException(struct _Unwind_Exception *);
+uintptr_t _Unwind_GetGR(struct _Unwind_Context *, int);
+void _Unwind_SetGR(struct _Unwind_Context *, int, uintptr_t);
+uintptr_t _Unwind_GetIP(struct _Unwind_Context *);
+uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *, int *);
+uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
+void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t);
+uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *);
+uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *);
+uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *);
+uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *);
+
+typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
+ void *);
+_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *);
+void *_Unwind_FindEnclosingFunction(void *);
+
+void __register_frame(const void *);
+void __register_frame_info(const void *, void *);
+void __deregister_frame(const void *);
+void *__deregister_frame_info(const void *);
+
+#ifdef _UNWIND_GCC_EXTENSIONS
+void *_Unwind_Find_FDE(void *, struct dwarf_eh_bases *);
+#endif
+
+__END_DECLS
+
+#endif // _UNWIND_H
Index: contrib/netbsd-unwind/unwind_registers.S
===================================================================
--- /dev/null
+++ contrib/netbsd-unwind/unwind_registers.S
@@ -0,0 +1,1336 @@
+//===------------------------- unwind_registers.S -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//
+// Abstracts accessing local vs remote address spaces.
+//
+//===----------------------------------------------------------------------===//
+#include <machine/asm.h>
+
+#ifdef __i386__
+ .hidden _ZN7_Unwind13Registers_x86C1Ev
+ENTRY(_ZN7_Unwind13Registers_x86C1Ev)
+ pushl %eax
+ movl 8(%esp), %eax /* Load this */
+ /* Save all registers except EAX, EIP and ESP */
+ /* Skip ECX */
+ /* Skip EDX */
+ movl %ebx, 12(%eax)
+ movl %ebp, 20(%eax)
+ movl %esi, 24(%eax)
+ movl %edi, 28(%eax)
+
+ leal 8(%esp), %edx /* Compute ESP from the call site */
+ movl %edx, 16(%eax) /* ...and store it as ESP */
+ movl 4(%esp), %edx /* Load return address */
+ movl %edx, 32(%eax) /* ...and store it as EIP */
+ popl %edx /* Take old EAX from stack */
+ movl %edx, 0(%eax) /* ...and store it */ // XXX skip
+ ret
+
+ .hidden _ZNK7_Unwind13Registers_x866jumptoEv
+ENTRY(_ZNK7_Unwind13Registers_x866jumptoEv)
+ movl 4(%esp), %eax /* Load this */
+ movl 16(%eax), %edx /* Load new stack pointer */
+ subl $4, %edx /* Reserve space on new stack for EIP */
+ movl 32(%eax), %ebx /* Load new EIP */
+ movl %ebx, 0(%edx) /* ...and save it on the new stack */
+ pushl %edx /* Save new stack pointer on old stack */
+ /* New stack is prepared, now restore all registers except ESP */
+ /* EAX is the index register and must be restored last */
+ movl 4(%eax), %ecx
+ movl 8(%eax), %edx
+ movl 12(%eax), %ebx
+ movl 20(%eax), %ebp
+ /* 16 is ESP */
+ movl 24(%eax), %esi
+ movl 28(%eax), %edi
+ movl 0(%eax), %eax
+ /* Now load new stack pointer pushed on the old stack earlier */
+ popl %esp
+ /* Return address is already on the new stack. */
+ ret
+#endif
+
+#ifdef __x86_64
+ .hidden _ZN7_Unwind16Registers_x86_64C1Ev
+ENTRY(_ZN7_Unwind16Registers_x86_64C1Ev)
+ /* RDI == this */
+ /* Skip RAX */
+ /* Skip RDX */
+ /* Skip RCX */
+ movq %rbx, 24(%rdi)
+ /* Skip RSI */
+ /* Skip RDI */
+ movq %rbp, 48(%rdi)
+ leaq 8(%rsp), %rax
+ movq %rax, 56(%rdi)
+ /* Skip R8 */
+ /* Skip R9 */
+ /* Skip R10 */
+ /* Skip R11 */
+ movq %r12, 96(%rdi)
+ movq %r13, 104(%rdi)
+ movq %r14, 112(%rdi)
+ movq %r15, 120(%rdi)
+ movq (%rsp), %rax
+ movq %rax, 128(%rdi)
+ ret
+
+ .hidden _ZNK7_Unwind16Registers_x86_646jumptoEv
+ENTRY(_ZNK7_Unwind16Registers_x86_646jumptoEv)
+ /* RDI == this */
+ movq 56(%rdi), %rax
+ subq $8, %rax /* Reserve space on new stack for RIP */
+ movq 128(%rdi), %rbx /* Load new RIP */
+ movq %rbx, 0(%rax) /* ...and save it on the new stack */
+ pushq %rax /* Save new stack pointer on old stack */
+ /* New stack is prepared, now restore all registers */
+ movq 0(%rdi), %rax
+ movq 8(%rdi), %rdx
+ movq 16(%rdi), %rcx
+ movq 24(%rdi), %rbx
+ movq 32(%rdi), %rsi
+ /* RDI restored later as it is still used as index register */
+ movq 48(%rdi), %rbp
+ /* RSP is restored later */
+ movq 64(%rdi), %r8
+ movq 72(%rdi), %r9
+ movq 80(%rdi), %r10
+ movq 88(%rdi), %r11
+ movq 96(%rdi), %r12
+ movq 104(%rdi), %r13
+ movq 112(%rdi), %r14
+ movq 120(%rdi), %r15
+ movq 40(%rdi), %rdi
+ /* Now load new stack pointer pushed on the old stack earlier */
+ popq %rsp
+ /* Return address is already on the new stack. */
+ ret
+#endif
+
+#ifdef __powerpc__
+ .hidden _ZN7_Unwind15Registers_ppc32C1Ev
+ENTRY(_ZN7_Unwind15Registers_ppc32C1Ev)
+ /* TODO: skip non-callee-safe registers */
+ stw %r0, 0(%r3)
+ stw %r1, 4(%r3)
+ stw %r2, 8(%r3)
+ stw %r3, 12(%r3)
+ stw %r4, 16(%r3)
+ stw %r5, 20(%r3)
+ stw %r6, 24(%r3)
+ stw %r7, 28(%r3)
+ stw %r8, 32(%r3)
+ stw %r9, 36(%r3)
+ stw %r10, 40(%r3)
+ stw %r11, 44(%r3)
+ stw %r12, 48(%r3)
+ stw %r13, 52(%r3)
+ stw %r14, 56(%r3)
+ stw %r15, 60(%r3)
+ stw %r16, 64(%r3)
+ stw %r17, 68(%r3)
+ stw %r18, 72(%r3)
+ stw %r19, 76(%r3)
+ stw %r20, 80(%r3)
+ stw %r21, 84(%r3)
+ stw %r22, 88(%r3)
+ stw %r23, 92(%r3)
+ stw %r24, 96(%r3)
+ stw %r25,100(%r3)
+ stw %r26,104(%r3)
+ stw %r27,108(%r3)
+ stw %r28,112(%r3)
+ stw %r29,116(%r3)
+ stw %r30,120(%r3)
+ stw %r31,124(%r3)
+ mflr %r0
+ stw %r0, 136(%r3) /* SRR0 */
+ mfcr %r0
+ stw %r0, 132(%r3) /* CR */
+
+ stfd %f0, 144(%r3)
+ stfd %f1, 152(%r3)
+ stfd %f2, 160(%r3)
+ stfd %f3, 168(%r3)
+ stfd %f4, 176(%r3)
+ stfd %f5, 184(%r3)
+ stfd %f6, 192(%r3)
+ stfd %f7, 200(%r3)
+ stfd %f8, 208(%r3)
+ stfd %f9, 216(%r3)
+ stfd %f10, 224(%r3)
+ stfd %f11, 232(%r3)
+ stfd %f12, 240(%r3)
+ stfd %f13, 248(%r3)
+ stfd %f14, 256(%r3)
+ stfd %f15, 264(%r3)
+ stfd %f16, 272(%r3)
+ stfd %f17, 280(%r3)
+ stfd %f18, 288(%r3)
+ stfd %f19, 296(%r3)
+ stfd %f20, 304(%r3)
+ stfd %f21, 312(%r3)
+ stfd %f22, 320(%r3)
+ stfd %f23, 328(%r3)
+ stfd %f24, 336(%r3)
+ stfd %f25, 344(%r3)
+ stfd %f26, 352(%r3)
+ stfd %f27, 360(%r3)
+ stfd %f28, 368(%r3)
+ stfd %f29, 376(%r3)
+ stfd %f30, 384(%r3)
+ stfd %f31, 392(%r3)
+
+ /* LR is undefined */
+ blr
+
+ .hidden _ZNK7_Unwind15Registers_ppc326jumptoEv
+ENTRY(_ZNK7_Unwind15Registers_ppc326jumptoEv)
+ lfd %f0, 144(%r3)
+ lfd %f1, 152(%r3)
+ lfd %f2, 160(%r3)
+ lfd %f3, 168(%r3)
+ lfd %f4, 176(%r3)
+ lfd %f5, 184(%r3)
+ lfd %f6, 192(%r3)
+ lfd %f7, 200(%r3)
+ lfd %f8, 208(%r3)
+ lfd %f9, 216(%r3)
+ lfd %f10, 224(%r3)
+ lfd %f11, 232(%r3)
+ lfd %f12, 240(%r3)
+ lfd %f13, 248(%r3)
+ lfd %f14, 256(%r3)
+ lfd %f15, 264(%r3)
+ lfd %f16, 272(%r3)
+ lfd %f17, 280(%r3)
+ lfd %f18, 288(%r3)
+ lfd %f19, 296(%r3)
+ lfd %f20, 304(%r3)
+ lfd %f21, 312(%r3)
+ lfd %f22, 320(%r3)
+ lfd %f23, 328(%r3)
+ lfd %f24, 336(%r3)
+ lfd %f25, 344(%r3)
+ lfd %f26, 352(%r3)
+ lfd %f27, 360(%r3)
+ lfd %f28, 368(%r3)
+ lfd %f29, 376(%r3)
+ lfd %f30, 384(%r3)
+ lfd %f31, 392(%r3)
+
+ lwz %r2, 8(%r3)
+ /* skip r3 for now */
+ lwz %r4, 16(%r3)
+ lwz %r5, 20(%r3)
+ lwz %r6, 24(%r3)
+ lwz %r7, 28(%r3)
+ lwz %r8, 32(%r3)
+ lwz %r9, 36(%r3)
+ lwz %r10, 40(%r3)
+ lwz %r11, 44(%r3)
+ lwz %r12, 48(%r3)
+ lwz %r13, 52(%r3)
+ lwz %r14, 56(%r3)
+ lwz %r15, 60(%r3)
+ lwz %r16, 64(%r3)
+ lwz %r17, 68(%r3)
+ lwz %r18, 72(%r3)
+ lwz %r19, 76(%r3)
+ lwz %r20, 80(%r3)
+ lwz %r21, 84(%r3)
+ lwz %r22, 88(%r3)
+ lwz %r23, 92(%r3)
+ lwz %r24, 96(%r3)
+ lwz %r25,100(%r3)
+ lwz %r26,104(%r3)
+ lwz %r27,108(%r3)
+ lwz %r28,112(%r3)
+ lwz %r29,116(%r3)
+ lwz %r30,120(%r3)
+ lwz %r31,124(%r3)
+
+ lwz %r0, 128(%r3) /* LR */
+ mtlr %r0
+ lwz %r0, 132(%r3) /* CR */
+ mtcr %r0
+ lwz %r0, 136(%r3) /* SRR0 */
+ mtctr %r0
+
+ lwz %r0, 0(%r3) /* do r0 now */
+ lwz %r1, 4(%r3) /* do sp now */
+ lwz %r3, 12(%r3) /* do r3 last */
+ bctr
+#endif
+
+#ifdef __aarch64__
+ .hidden _ZN7_Unwind17Registers_aarch64C1Ev
+ENTRY(_ZN7_Unwind17Registers_aarch64C1Ev)
+ stp x0, x1, [x0]
+ add x0, x0, #16
+ stp x2, x3, [x0], #16
+ stp x4, x5, [x0], #16
+ stp x6, x7, [x0], #16
+ stp x8, x9, [x0], #16
+ stp x10, x11, [x0], #16
+ stp x12, x13, [x0], #16
+ stp x14, x15, [x0], #16
+ stp x16, x17, [x0], #16
+ stp x18, x19, [x0], #16
+ stp x20, x22, [x0], #16
+ stp x22, x24, [x0], #16
+ stp x24, x26, [x0], #16
+ stp x26, x27, [x0], #16
+ stp x28, x29, [x0], #16
+ mov x1, sp
+ stp x30, x1, [x0], #16
+
+ add x0, x0, #8
+ str xzr, [x0], #8
+
+ stp q0, q1, [x0], #64
+ stp q2, q3, [x0], #64
+ stp q4, q5, [x0], #64
+ stp q6, q7, [x0], #64
+ stp q8, q9, [x0], #64
+ stp q10, q11, [x0], #64
+ stp q12, q13, [x0], #64
+ stp q14, q15, [x0], #64
+ stp q16, q17, [x0], #64
+ stp q18, q19, [x0], #64
+ stp q20, q21, [x0], #64
+ stp q22, q23, [x0], #64
+ stp q24, q25, [x0], #64
+ stp q26, q27, [x0], #64
+ stp q28, q29, [x0], #64
+ stp q30, q31, [x0], #64
+
+ ret
+END(_ZN7_Unwind17Registers_aarch64C1Ev)
+
+ .hidden _ZNK7_Unwind17Registers_aarch646jumptoEv
+ENTRY(_ZNK7_Unwind17Registers_aarch646jumptoEv)
+ ldp x2, x3, [x0, #16]
+ ldp x4, x6, [x0, #32]
+ ldp x6, x7, [x0, #48]
+ ldp x8, x9, [x0, #64]
+ ldp x10, x11, [x0, #80]
+ ldp x12, x13, [x0, #96]
+ ldp x14, x16, [x0, #112]
+ ldp x16, x17, [x0, #128]
+ ldp x18, x19, [x0, #144]
+ ldp x20, x21, [x0, #160]
+ ldp x22, x23, [x0, #176]
+ ldp x24, x26, [x0, #192]
+ ldp x26, x27, [x0, #208]
+ ldp x28, x29, [x0, #224]
+ ldp x30, x1, [x0, #240]
+ mov sp, x1
+
+ ldp x0, x1, [x0, #0]
+ ret
+END(_ZNK7_Unwind17Registers_aarch646jumptoEv)
+#endif /* __aarch64__ */
+
+#if defined(__arm__)
+ .fpu vfpv3
+ .hidden _ZN7_Unwind15Registers_arm32C1Ev
+ARM_ENTRY(_ZN7_Unwind15Registers_arm32C1Ev)
+ stmia r0, {r0-r14}
+ str lr, [r0, #60] /* PC */
+ mrs r1, cpsr
+ str r1, [r0, #64] /* CPSR */
+ mov r1, #0
+ str r1, [r0, #68]
+ RET
+END(_ZN7_Unwind15Registers_arm32C1Ev)
+
+ .hidden _ZN7_Unwind15Registers_arm328lazyVFP1Ev
+ARM_ENTRY(_ZN7_Unwind15Registers_arm328lazyVFP1Ev)
+ add r0, #72
+ vstmia r0, {d0-d15}
+ RET
+END(_ZN7_Unwind15Registers_arm328lazyVFP1Ev)
+
+ .hidden _ZN7_Unwind15Registers_arm328lazyVFP3Ev
+ARM_ENTRY(_ZN7_Unwind15Registers_arm328lazyVFP3Ev)
+ add r0, #200
+ vstmia r0, {d16-d31}
+ RET
+END(_ZN7_Unwind15Registers_arm328lazyVFP3Ev)
+
+ .hidden _ZNK7_Unwind15Registers_arm326jumptoEv
+ARM_ENTRY(_ZNK7_Unwind15Registers_arm326jumptoEv)
+ ldrb r1, [r0, #68]
+ tst r1, #1
+ beq .Lnovfp1
+ add r2, r0, #72
+ vldmia r2, {d0-d15}
+.Lnovfp1:
+ tst r1, #2
+ beq .Lnovfp3
+ add r2, r0, #200
+ vldmia r2, {d16-d31}
+.Lnovfp3:
+ ldr r1, [r0, #64]
+ msr cpsr_sxc, r1
+ ldmia r0, {r0-r15}
+END(_ZNK7_Unwind15Registers_arm326jumptoEv)
+#endif
+
+#if defined(__vax__)
+ .hidden _ZN7_Unwind13Registers_vaxC1Ev
+ENTRY(_ZN7_Unwind13Registers_vaxC1Ev, R0)
+ subl2 $4, %sp
+ movl 4(%ap), %r0
+ movl %r1, 4(%r0)
+ movl %r2, 8(%r0)
+ movl %r3, 12(%r0)
+ movl %r4, 16(%r0)
+ movl %r5, 20(%r0)
+ movl %r6, 24(%r0)
+ movl %r7, 28(%r0)
+ movl %r8, 32(%r0)
+ movl %r9, 36(%r0)
+ movl %r10, 40(%r0)
+ movl %r11, 44(%r0)
+ movl 8(%fp), 48(%r0)
+ movl 12(%fp), 52(%r0)
+ addl3 $36, %sp, 56(%r0)
+ /* Return PC */
+ movl 16(%fp), 60(%r0)
+ /* Load saved value of r0 as r1 */
+ movl 20(%fp), 0(%r0)
+ /* Saved PSW */
+ movl 4(%fp), 64(%r0)
+ ret
+END(_ZN7_Unwind13Registers_vaxC1Ev)
+
+ .hidden _ZNK7_Unwind13Registers_vax6jumptoEv
+ENTRY(_ZNK7_Unwind13Registers_vax6jumptoEv, 0)
+ subl2 $4, %sp
+ movl 4(%ap), %r0
+ movl 4(%r0), %r1
+ movl 8(%r0), %r2
+ movl 12(%r0), %r3
+ movl 16(%r0), %r4
+ movl 20(%r0), %r5
+ movl 24(%r0), %r6
+ movl 28(%r0), %r7
+ movl 32(%r0), %r8
+ movl 36(%r0), %r9
+ movl 40(%r0), %r10
+ movl 44(%r0), %r11
+ movl 48(%r0), %r12
+ movl 52(%r0), %r13
+ movl 56(%r0), %r14
+ movl 60(%r0), -(%sp)
+ movl 0(%r0), %r0
+ /* XXX restore PSW */
+ rsb
+END(_ZNK7_Unwind13Registers_vax6jumptoEv)
+#endif
+
+#if defined(__m68k__)
+ENTRY(_ZN7_Unwind14Registers_M68KC1Ev)
+ move.l 4(%sp), %a0
+ movem.l %d0-%d7/%a0-%a7, (%a0)
+ fmovem %fp0-%fp7, 72(%a0)
+ move.l 0(%sp), %a1
+ move.l %a1, 64(%a0)
+ addq.l #4, 60(%a0)
+ rts
+END(_ZN7_Unwind14Registers_M68KC1Ev)
+
+ENTRY(_ZNK7_Unwind14Registers_M68K6jumptoEv)
+ move.l 4(%sp), %a0
+ subq.l #4, 60(%a0)
+ move.l 64(%a0), %a1
+ move.l 60(%a0), %a2
+ move.l %a1, (%a2)
+ fmovem 72(%a0), %fp0-%fp7
+ movem.l (%a0), %d0-%d7/%a0-%a7
+ rts
+END(_ZNK7_Unwind14Registers_M68K6jumptoEv)
+#endif
+
+#if defined(__sh3__)
+ .hidden _ZN7_Unwind13Registers_SH3C1Ev
+ENTRY(_ZN7_Unwind13Registers_SH3C1Ev)
+ add #64, r4
+ mov.l r8, @-r15
+ sts.l pr, @-r15
+ mov.l @r15+, r8
+ mov.l r8, @r4
+ mov.l @r15+, r8
+
+ mov.l r15, @-r4
+ mov.l r14, @-r4
+ mov.l r13, @-r4
+ mov.l r12, @-r4
+ mov.l r11, @-r4
+ mov.l r10, @-r4
+ mov.l r9, @-r4
+ mov.l r8, @-r4
+ mov.l r7, @-r4
+ mov.l r6, @-r4
+ mov.l r5, @-r4
+ add #-4, r4
+ mov.l r3, @-r4
+ mov.l r2, @-r4
+ mov.l r1, @-r4
+ mov.l r0, @-r4
+ rts
+ mov.l r4, @(16,r4)
+SET_ENTRY_SIZE(_ZN7_Unwind13Registers_SH3C1Ev)
+
+ .hidden _ZNK7_Unwind13Registers_SH36jumptoEv
+ENTRY(_ZNK7_Unwind13Registers_SH36jumptoEv)
+ mov r4, r0
+ add #4, r0
+ mov.l @r0+, r1
+ mov.l @r0+, r2
+ mov.l @r0+, r3
+ mov.l @r0+, r4
+ mov.l @r0+, r5
+ mov.l @r0+, r6
+ mov.l @r0+, r7
+ mov.l @r0+, r8
+ mov.l @r0+, r9
+ mov.l @r0+, r10
+ mov.l @r0+, r11
+ mov.l @r0+, r12
+ mov.l @r0+, r13
+ mov.l @(12, r0), r14
+ lds r14, pr
+ mov.l @r0+, r14
+ mov.l @r0+, r15
+ mov.l @r0, r0
+ jmp @r0
+ nop
+SET_ENTRY_SIZE(_ZNK7_Unwind13Registers_SH36jumptoEv)
+#endif
+
+#if defined(__sparc64__)
+#include <machine/trap.h>
+ .register %g2, #ignore
+ .register %g3, #ignore
+ .register %g6, #ignore
+ .register %g7, #ignore
+ .hidden _ZN7_Unwind17Registers_SPARC64C1Ev
+ENTRY(_ZN7_Unwind17Registers_SPARC64C1Ev)
+ t ST_FLUSHWIN
+ stx %g0, [%o0 + 0]
+ stx %g1, [%o0 + 8]
+ stx %g2, [%o0 + 16]
+ stx %g3, [%o0 + 24]
+ stx %g4, [%o0 + 32]
+ stx %g5, [%o0 + 40]
+ stx %g6, [%o0 + 48]
+ stx %g7, [%o0 + 56]
+ stx %o0, [%o0 + 64]
+ stx %o1, [%o0 + 72]
+ stx %o2, [%o0 + 80]
+ stx %o3, [%o0 + 88]
+ stx %o4, [%o0 + 96]
+ stx %o5, [%o0 + 104]
+ stx %o6, [%o0 + 112]
+ stx %o7, [%o0 + 120]
+ stx %l0, [%o0 + 128]
+ stx %l1, [%o0 + 136]
+ stx %l2, [%o0 + 144]
+ stx %l3, [%o0 + 152]
+ stx %l4, [%o0 + 160]
+ stx %l5, [%o0 + 168]
+ stx %l6, [%o0 + 176]
+ stx %l7, [%o0 + 184]
+ stx %i0, [%o0 + 192]
+ stx %i1, [%o0 + 200]
+ stx %i2, [%o0 + 208]
+ stx %i3, [%o0 + 216]
+ stx %i4, [%o0 + 224]
+ stx %i5, [%o0 + 232]
+ stx %i6, [%o0 + 240]
+ stx %i7, [%o0 + 248]
+ add %o7, 8, %g1
+ retl
+ stx %g1, [%o0 + 256]
+END(_ZN7_Unwind17Registers_SPARC64C1Ev)
+
+ .hidden _ZNK7_Unwind17Registers_SPARC646jumptoEv
+ENTRY(_ZNK7_Unwind17Registers_SPARC646jumptoEv)
+ t ST_FLUSHWIN
+ ldx [%o0 + 0], %g0
+ ldx [%o0 + 8], %g1
+ ldx [%o0 + 16], %g2
+ ldx [%o0 + 24], %g3
+ ldx [%o0 + 32], %g4
+ ldx [%o0 + 40], %g5
+ ldx [%o0 + 48], %g6
+ ldx [%o0 + 56], %g7
+ ldx [%o0 + 72], %o1
+ ldx [%o0 + 80], %o2
+ ldx [%o0 + 88], %o3
+ ldx [%o0 + 96], %o4
+ ldx [%o0 + 104], %o5
+ ldx [%o0 + 112], %g1
+ sub %g1, 2047, %o6
+ ldx [%o0 + 120], %o7
+ ldx [%o0 + 128], %l0
+ ldx [%o0 + 136], %l1
+ ldx [%o0 + 144], %l2
+ ldx [%o0 + 152], %l3
+ ldx [%o0 + 160], %l4
+ ldx [%o0 + 168], %l5
+ ldx [%o0 + 176], %l6
+ ldx [%o0 + 184], %l7
+ ldx [%o0 + 192], %i0
+ ldx [%o0 + 200], %i1
+ ldx [%o0 + 208], %i2
+ ldx [%o0 + 216], %i3
+ ldx [%o0 + 224], %i4
+ ldx [%o0 + 232], %i5
+ ldx [%o0 + 240], %i6
+ ldx [%o0 + 248], %i7
+ ldx [%o0 + 256], %g1
+ jmpl %g1, %g0
+ ldx [%o0 + 64], %o0
+END(_ZNK7_Unwind17Registers_SPARC646jumptoEv)
+#elif defined(__sparc__)
+#include <machine/trap.h>
+
+ .hidden _ZN7_Unwind15Registers_SPARCC1Ev
+ENTRY(_ZN7_Unwind15Registers_SPARCC1Ev)
+ t ST_FLUSHWIN
+ st %g0, [%o0 + 0]
+ st %g1, [%o0 + 4]
+ st %g2, [%o0 + 8]
+ st %g3, [%o0 + 12]
+ st %g4, [%o0 + 16]
+ st %g5, [%o0 + 20]
+ st %g6, [%o0 + 24]
+ st %g7, [%o0 + 28]
+ st %o0, [%o0 + 32]
+ st %o1, [%o0 + 36]
+ st %o2, [%o0 + 40]
+ st %o3, [%o0 + 44]
+ st %o4, [%o0 + 48]
+ st %o5, [%o0 + 52]
+ st %o6, [%o0 + 56]
+ st %o7, [%o0 + 60]
+ st %l0, [%o0 + 64]
+ st %l1, [%o0 + 68]
+ st %l2, [%o0 + 72]
+ st %l3, [%o0 + 76]
+ st %l4, [%o0 + 80]
+ st %l5, [%o0 + 84]
+ st %l6, [%o0 + 88]
+ st %l7, [%o0 + 92]
+ st %i0, [%o0 + 96]
+ st %i1, [%o0 + 100]
+ st %i2, [%o0 + 104]
+ st %i3, [%o0 + 108]
+ st %i4, [%o0 + 112]
+ st %i5, [%o0 + 116]
+ st %i6, [%o0 + 120]
+ st %i7, [%o0 + 124 ]
+ add %o7, 8, %g1
+ retl
+ st %g1, [%o0 + 128]
+END(_ZN7_Unwind15Registers_SPARCC1Ev)
+
+ .hidden _ZNK7_Unwind15Registers_SPARC6jumptoEv
+ENTRY(_ZNK7_Unwind15Registers_SPARC6jumptoEv)
+ t ST_FLUSHWIN
+ ld [%o0 + 0], %g0
+ ld [%o0 + 4], %g1
+ ld [%o0 + 8], %g2
+ ld [%o0 + 12], %g3
+ ld [%o0 + 16], %g4
+ ld [%o0 + 20], %g5
+ ld [%o0 + 24], %g6
+ ld [%o0 + 28], %g7
+ ld [%o0 + 36], %o1
+ ld [%o0 + 40], %o2
+ ld [%o0 + 44], %o3
+ ld [%o0 + 48], %o4
+ ld [%o0 + 52], %o5
+ ld [%o0 + 56], %o6
+ ld [%o0 + 60], %o7
+ ld [%o0 + 64], %l0
+ ld [%o0 + 68], %l1
+ ld [%o0 + 72], %l2
+ ld [%o0 + 76], %l3
+ ld [%o0 + 80], %l4
+ ld [%o0 + 84], %l5
+ ld [%o0 + 88], %l6
+ ld [%o0 + 92], %l7
+ ld [%o0 + 96], %i0
+ ld [%o0 + 100], %i1
+ ld [%o0 + 104], %i2
+ ld [%o0 + 108], %i3
+ ld [%o0 + 112], %i4
+ ld [%o0 + 116], %i5
+ ld [%o0 + 120], %i6
+ ld [%o0 + 124], %i7
+ ld [%o0 + 128], %g1
+ jmpl %g1, %g0
+ ld [%o0 + 32], %o0
+END(_ZNK7_Unwind15Registers_SPARC6jumptoEv)
+#endif
+
+#if defined(__alpha__)
+ .set nomacro
+ .set noat
+ .hidden _ZN7_Unwind15Registers_AlphaC1Ev
+LEAF_NOPROFILE(_ZN7_Unwind15Registers_AlphaC1Ev, 1)
+ stq $0, 0($16)
+ stq $1, 8($16)
+ stq $2, 16($16)
+ stq $3, 24($16)
+ stq $4, 32($16)
+ stq $5, 40($16)
+ stq $6, 48($16)
+ stq $7, 56($16)
+ stq $8, 64($16)
+ stq $9, 72($16)
+ stq $10, 80($16)
+ stq $11, 88($16)
+ stq $12, 96($16)
+ stq $13, 104($16)
+ stq $14, 112($16)
+ stq $15, 120($16)
+ stq $16, 128($16)
+ stq $17, 136($16)
+ stq $18, 144($16)
+ stq $19, 152($16)
+ stq $20, 160($16)
+ stq $21, 168($16)
+ stq $22, 176($16)
+ stq $23, 184($16)
+ stq $24, 192($16)
+ stq $25, 200($16)
+ stq $26, 208($16)
+ stq $27, 216($16)
+ stq $28, 224($16)
+ stq $29, 232($16)
+ stq $30, 240($16)
+ stq $26, 248($16)
+
+ stt $f0, 256($16)
+ stt $f1, 264($16)
+ stt $f2, 272($16)
+ stt $f3, 280($16)
+ stt $f4, 288($16)
+ stt $f5, 296($16)
+ stt $f6, 304($16)
+ stt $f7, 312($16)
+ stt $f8, 320($16)
+ stt $f9, 328($16)
+ stt $f10, 336($16)
+ stt $f11, 344($16)
+ stt $f12, 352($16)
+ stt $f13, 360($16)
+ stt $f14, 368($16)
+ stt $f15, 376($16)
+ stt $f16, 384($16)
+ stt $f17, 392($16)
+ stt $f18, 400($16)
+ stt $f19, 408($16)
+ stt $f20, 416($16)
+ stt $f21, 424($16)
+ stt $f22, 432($16)
+ stt $f23, 440($16)
+ stt $f24, 448($16)
+ stt $f25, 456($16)
+ stt $f26, 464($16)
+ stt $f27, 472($16)
+ stt $f28, 480($16)
+ stt $f29, 488($16)
+ stt $f30, 496($16)
+ ret $31, ($26), 1
+END(_ZN7_Unwind15Registers_AlphaC1Ev)
+
+ .set nomacro
+ .set noat
+ .hidden _ZNK7_Unwind15Registers_Alpha6jumptoEv
+LEAF_NOPROFILE(_ZNK7_Unwind15Registers_Alpha6jumptoEv, 1)
+ ldq $0, 0($16)
+ ldq $1, 8($16)
+ ldq $2, 16($16)
+ ldq $3, 24($16)
+ ldq $4, 32($16)
+ ldq $5, 40($16)
+ ldq $6, 48($16)
+ ldq $7, 56($16)
+ ldq $8, 64($16)
+ ldq $9, 72($16)
+ ldq $10, 80($16)
+ ldq $11, 88($16)
+ ldq $12, 96($16)
+ ldq $13, 104($16)
+ ldq $14, 112($16)
+ ldq $15, 120($16)
+ ldq $17, 136($16)
+ ldq $18, 144($16)
+ ldq $19, 152($16)
+ ldq $20, 160($16)
+ ldq $21, 168($16)
+ ldq $22, 176($16)
+ ldq $23, 184($16)
+ ldq $24, 192($16)
+ ldq $25, 200($16)
+ ldq $27, 216($16)
+ ldq $28, 224($16)
+ ldq $29, 232($16)
+ ldq $30, 240($16)
+ ldq $26, 248($16)
+
+ ldt $f0, 256($16)
+ ldt $f1, 264($16)
+ ldt $f2, 272($16)
+ ldt $f3, 280($16)
+ ldt $f4, 288($16)
+ ldt $f5, 296($16)
+ ldt $f6, 304($16)
+ ldt $f7, 312($16)
+ ldt $f8, 320($16)
+ ldt $f9, 328($16)
+ ldt $f10, 336($16)
+ ldt $f11, 344($16)
+ ldt $f12, 352($16)
+ ldt $f13, 360($16)
+ ldt $f14, 368($16)
+ ldt $f15, 376($16)
+ ldt $f16, 384($16)
+ ldt $f17, 392($16)
+ ldt $f18, 400($16)
+ ldt $f19, 408($16)
+ ldt $f20, 416($16)
+ ldt $f21, 424($16)
+ ldt $f22, 432($16)
+ ldt $f23, 440($16)
+ ldt $f24, 448($16)
+ ldt $f25, 456($16)
+ ldt $f26, 464($16)
+ ldt $f27, 472($16)
+ ldt $f28, 480($16)
+ ldt $f29, 488($16)
+ ldt $f30, 496($16)
+ ldq $16, 128($16)
+ ret $31, ($26), 1
+END(_ZNK7_Unwind15Registers_Alpha6jumptoEv)
+#endif
+
+#if defined(__mips_n64) || defined(__mips_n32)
+ .set noat
+LEAF(_ZN7_Unwind16Registers_MIPS64C1Ev)
+#if 0
+ FP_S $f0, 256($4)
+ FP_S $f1, 264($4)
+ FP_S $f2, 272($4)
+ FP_S $f3, 280($4)
+ FP_S $f4, 288($4)
+ FP_S $f5, 296($4)
+ FP_S $f6, 304($4)
+ FP_S $f7, 312($4)
+ FP_S $f8, 320($4)
+ FP_S $f9, 328($4)
+ FP_S $f10, 336($4)
+ FP_S $f11, 344($4)
+ FP_S $f12, 352($4)
+ FP_S $f13, 360($4)
+ FP_S $f14, 368($4)
+ FP_S $f15, 376($4)
+ FP_S $f16, 384($4)
+ FP_S $f17, 392($4)
+ FP_S $f18, 400($4)
+ FP_S $f19, 408($4)
+ FP_S $f20, 416($4)
+ FP_S $f21, 424($4)
+ FP_S $f22, 432($4)
+ FP_S $f23, 440($4)
+ FP_S $f24, 448($4)
+ FP_S $f25, 456($4)
+ FP_S $f26, 464($4)
+ FP_S $f27, 472($4)
+ FP_S $f28, 480($4)
+ FP_S $f29, 488($4)
+ FP_S $f30, 496($4)
+ FP_S $f31, 504($4)
+#endif
+ sd $31, 0($4)
+ sd $1, 4($4)
+ sd $2, 8($4)
+ sd $3, 12($4)
+ sd $4, 16($4)
+ sd $5, 20($4)
+ sd $6, 24($4)
+ sd $7, 28($4)
+ sd $8, 32($4)
+ sd $9, 36($4)
+ sd $10, 40($4)
+ sd $11, 44($4)
+ sd $12, 48($4)
+ sd $13, 52($4)
+ sd $14, 56($4)
+ sd $15, 60($4)
+ sd $16, 64($4)
+ sd $17, 68($4)
+ sd $18, 72($4)
+ sd $19, 76($4)
+ sd $20, 80($4)
+ sd $21, 84($4)
+ sd $22, 88($4)
+ sd $23, 92($4)
+ sd $24, 96($4)
+ sd $25, 100($4)
+ sd $26, 104($4)
+ sd $27, 108($4)
+ sd $28, 112($4)
+ sd $29, 116($4)
+ sd $30, 120($4)
+ sd $31, 124($4)
+ jr $31
+ nop
+END(_ZN7_Unwind16Registers_MIPS64C1Ev)
+
+LEAF(_ZNK7_Unwind16Registers_MIPS646jumptoEv)
+#if 0
+ FP_L $f0, 256($4)
+ FP_L $f1, 264($4)
+ FP_L $f2, 272($4)
+ FP_L $f3, 280($4)
+ FP_L $f4, 288($4)
+ FP_L $f5, 296($4)
+ FP_L $f6, 304($4)
+ FP_L $f7, 312($4)
+ FP_L $f8, 320($4)
+ FP_L $f9, 328($4)
+ FP_L $f10, 336($4)
+ FP_L $f11, 344($4)
+ FP_L $f12, 352($4)
+ FP_L $f13, 360($4)
+ FP_L $f14, 368($4)
+ FP_L $f15, 376($4)
+ FP_L $f16, 384($4)
+ FP_L $f17, 392($4)
+ FP_L $f18, 400($4)
+ FP_L $f19, 408($4)
+ FP_L $f20, 416($4)
+ FP_L $f21, 424($4)
+ FP_L $f22, 432($4)
+ FP_L $f23, 440($4)
+ FP_L $f24, 448($4)
+ FP_L $f25, 456($4)
+ FP_L $f26, 464($4)
+ FP_L $f27, 472($4)
+ FP_L $f28, 480($4)
+ FP_L $f29, 488($4)
+ FP_L $f30, 496($4)
+ FP_L $f31, 504($4)
+#endif
+
+ ld $31, 0($4)
+ ld $1, 8($4)
+ ld $2, 16($4)
+ ld $3, 24($4)
+ ld $5, 40($4)
+ ld $6, 48($4)
+ ld $7, 56($4)
+ ld $8, 64($4)
+ ld $9, 72($4)
+ ld $10, 80($4)
+ ld $11, 88($4)
+ ld $12, 96($4)
+ ld $13, 104($4)
+ ld $14, 112($4)
+ ld $15, 120($4)
+ ld $16, 128($4)
+ ld $17, 136($4)
+ ld $18, 144($4)
+ ld $19, 152($4)
+ ld $20, 160($4)
+ ld $21, 168($4)
+ ld $22, 176($4)
+ ld $23, 184($4)
+ ld $24, 192($4)
+ ld $25, 200($4)
+ ld $26, 208($4)
+ ld $27, 216($4)
+ ld $28, 224($4)
+ ld $29, 232($4)
+ ld $30, 240($4)
+ ld $4, 32($4)
+ jr $31
+ nop
+END(_ZNK7_Unwind16Registers_MIPS646jumptoEv)
+#elif defined(__mips__)
+ .set noat
+LEAF(_ZN7_Unwind14Registers_MIPSC1Ev)
+#if 0
+#if __mips > 1
+ FP_S $f0, 128($4)
+ FP_S $f1, 136($4)
+ FP_S $f2, 144($4)
+ FP_S $f3, 152($4)
+ FP_S $f4, 160($4)
+ FP_S $f5, 168($4)
+ FP_S $f6, 176($4)
+ FP_S $f7, 184($4)
+ FP_S $f8, 192($4)
+ FP_S $f9, 200($4)
+ FP_S $f10, 208($4)
+ FP_S $f11, 216($4)
+ FP_S $f12, 224($4)
+ FP_S $f13, 232($4)
+ FP_S $f14, 240($4)
+ FP_S $f15, 248($4)
+ FP_S $f16, 256($4)
+ FP_S $f17, 264($4)
+ FP_S $f18, 272($4)
+ FP_S $f19, 280($4)
+ FP_S $f20, 288($4)
+ FP_S $f21, 296($4)
+ FP_S $f22, 304($4)
+ FP_S $f23, 312($4)
+ FP_S $f24, 320($4)
+ FP_S $f25, 328($4)
+ FP_S $f26, 336($4)
+ FP_S $f27, 344($4)
+ FP_S $f28, 352($4)
+ FP_S $f29, 360($4)
+ FP_S $f30, 368($4)
+ FP_S $f31, 376($4)
+#endif
+#endif
+ sw $31, 0($4)
+ sw $1, 4($4)
+ sw $2, 8($4)
+ sw $3, 12($4)
+ sw $4, 16($4)
+ sw $5, 20($4)
+ sw $6, 24($4)
+ sw $7, 28($4)
+ sw $8, 32($4)
+ sw $9, 36($4)
+ sw $10, 40($4)
+ sw $11, 44($4)
+ sw $12, 48($4)
+ sw $13, 52($4)
+ sw $14, 56($4)
+ sw $15, 60($4)
+ sw $16, 64($4)
+ sw $17, 68($4)
+ sw $18, 72($4)
+ sw $19, 76($4)
+ sw $20, 80($4)
+ sw $21, 84($4)
+ sw $22, 88($4)
+ sw $23, 92($4)
+ sw $24, 96($4)
+ sw $25, 100($4)
+ sw $26, 104($4)
+ sw $27, 108($4)
+ sw $28, 112($4)
+ sw $29, 116($4)
+ sw $30, 120($4)
+ sw $31, 124($4)
+ jr $31
+ nop
+END(_ZN7_Unwind14Registers_MIPSC1Ev)
+
+LEAF(_ZNK7_Unwind14Registers_MIPS6jumptoEv)
+#if 0
+#if __mips > 1
+ FP_L $f0, 128($4)
+ FP_L $f1, 136($4)
+ FP_L $f2, 144($4)
+ FP_L $f3, 152($4)
+ FP_L $f4, 160($4)
+ FP_L $f5, 168($4)
+ FP_L $f6, 176($4)
+ FP_L $f7, 184($4)
+ FP_L $f8, 192($4)
+ FP_L $f9, 200($4)
+ FP_L $f10, 208($4)
+ FP_L $f11, 216($4)
+ FP_L $f12, 224($4)
+ FP_L $f13, 232($4)
+ FP_L $f14, 240($4)
+ FP_L $f15, 248($4)
+ FP_L $f16, 256($4)
+ FP_L $f17, 264($4)
+ FP_L $f18, 272($4)
+ FP_L $f19, 280($4)
+ FP_L $f20, 288($4)
+ FP_L $f21, 296($4)
+ FP_L $f22, 304($4)
+ FP_L $f23, 312($4)
+ FP_L $f24, 320($4)
+ FP_L $f25, 328($4)
+ FP_L $f26, 336($4)
+ FP_L $f27, 344($4)
+ FP_L $f28, 352($4)
+ FP_L $f29, 360($4)
+ FP_L $f30, 368($4)
+ FP_L $f31, 376($4)
+#endif
+#endif
+
+ lw $31, 0($4)
+ lw $1, 4($4)
+ lw $2, 8($4)
+ lw $3, 12($4)
+ lw $5, 20($4)
+ lw $6, 24($4)
+ lw $7, 28($4)
+ lw $8, 32($4)
+ lw $9, 36($4)
+ lw $10, 40($4)
+ lw $11, 44($4)
+ lw $12, 48($4)
+ lw $13, 52($4)
+ lw $14, 56($4)
+ lw $15, 60($4)
+ lw $16, 64($4)
+ lw $17, 68($4)
+ lw $18, 72($4)
+ lw $19, 76($4)
+ lw $20, 80($4)
+ lw $21, 84($4)
+ lw $22, 88($4)
+ lw $23, 92($4)
+ lw $24, 96($4)
+ lw $25, 100($4)
+ lw $26, 104($4)
+ lw $27, 108($4)
+ lw $28, 112($4)
+ lw $29, 116($4)
+ lw $30, 120($4)
+ lw $4, 16($4)
+ jr $31
+ nop
+END(_ZNK7_Unwind14Registers_MIPS6jumptoEv)
+#endif
+
+#if defined(__hppa__)
+LEAF_ENTRY_NOPROFILE(_ZN7_Unwind14Registers_HPPAC1Ev)
+ stw %r2, 0(%r26)
+ stw %r1, 4(%r26)
+ stw %r2, 8(%r26)
+ stw %r3, 12(%r26)
+ stw %r4, 16(%r26)
+ stw %r5, 20(%r26)
+ stw %r6, 24(%r26)
+ stw %r7, 28(%r26)
+ stw %r8, 32(%r26)
+ stw %r9, 36(%r26)
+ stw %r10, 40(%r26)
+ stw %r11, 44(%r26)
+ stw %r12, 48(%r26)
+ stw %r13, 52(%r26)
+ stw %r14, 56(%r26)
+ stw %r15, 60(%r26)
+ stw %r16, 64(%r26)
+ stw %r17, 68(%r26)
+ stw %r18, 72(%r26)
+ stw %r19, 76(%r26)
+ stw %r20, 80(%r26)
+ stw %r21, 84(%r26)
+ stw %r22, 88(%r26)
+ stw %r23, 92(%r26)
+ stw %r24, 96(%r26)
+ stw %r25, 100(%r26)
+ stw %r26, 104(%r26)
+ stw %r27, 108(%r26)
+ stw %r28, 112(%r26)
+ stw %r29, 116(%r26)
+ stw %r30, 120(%r26)
+ stw %r31, 124(%r26)
+ ldi 128, %r19
+ addl %r19, %r26, %r19
+ fstds,ma %fr4, 8(%r19)
+ fstds,ma %fr5, 8(%r19)
+ fstds,ma %fr6, 8(%r19)
+ fstds,ma %fr7, 8(%r19)
+ fstds,ma %fr8, 8(%r19)
+ fstds,ma %fr9, 8(%r19)
+ fstds,ma %fr10, 8(%r19)
+ fstds,ma %fr11, 8(%r19)
+ fstds,ma %fr12, 8(%r19)
+ fstds,ma %fr13, 8(%r19)
+ fstds,ma %fr14, 8(%r19)
+ fstds,ma %fr15, 8(%r19)
+ fstds,ma %fr16, 8(%r19)
+ fstds,ma %fr17, 8(%r19)
+ fstds,ma %fr18, 8(%r19)
+ fstds,ma %fr19, 8(%r19)
+ fstds,ma %fr20, 8(%r19)
+ fstds,ma %fr21, 8(%r19)
+ fstds,ma %fr22, 8(%r19)
+ fstds,ma %fr23, 8(%r19)
+ fstds,ma %fr24, 8(%r19)
+ fstds,ma %fr25, 8(%r19)
+ fstds,ma %fr19, 8(%r19)
+ fstds,ma %fr27, 8(%r19)
+ fstds,ma %fr28, 8(%r19)
+ fstds,ma %fr29, 8(%r19)
+ fstds,ma %fr30, 8(%r19)
+ fstds,ma %fr31, 8(%r19)
+ ldw 76(%r26), %r19
+ bv,n %r0(%r2)
+EXIT(_ZN7_Unwind14Registers_HPPAC1Ev)
+
+LEAF_ENTRY_NOPROFILE(_ZNK7_Unwind14Registers_HPPA6jumptoEv)
+ ldi 128, %r19
+ addl %r19, %r26, %r19
+ fldds,ma 8(%r19), %fr4
+ fldds,ma 8(%r19), %fr5
+ fldds,ma 8(%r19), %fr6
+ fldds,ma 8(%r19), %fr7
+ fldds,ma 8(%r19), %fr8
+ fldds,ma 8(%r19), %fr9
+ fldds,ma 8(%r19), %fr10
+ fldds,ma 8(%r19), %fr11
+ fldds,ma 8(%r19), %fr12
+ fldds,ma 8(%r19), %fr13
+ fldds,ma 8(%r19), %fr14
+ fldds,ma 8(%r19), %fr15
+ fldds,ma 8(%r19), %fr16
+ fldds,ma 8(%r19), %fr17
+ fldds,ma 8(%r19), %fr18
+ fldds,ma 8(%r19), %fr19
+ fldds,ma 8(%r19), %fr20
+ fldds,ma 8(%r19), %fr21
+ fldds,ma 8(%r19), %fr22
+ fldds,ma 8(%r19), %fr23
+ fldds,ma 8(%r19), %fr24
+ fldds,ma 8(%r19), %fr25
+ fldds,ma 8(%r19), %fr26
+ fldds,ma 8(%r19), %fr27
+ fldds,ma 8(%r19), %fr28
+ fldds,ma 8(%r19), %fr29
+ fldds,ma 8(%r19), %fr30
+ fldds,ma 8(%r19), %fr31
+ ldw 0(%r26), %r2
+ ldw 4(%r26), %r1
+ ldw 12(%r26), %r3
+ ldw 16(%r26), %r4
+ ldw 20(%r26), %r5
+ ldw 24(%r26), %r6
+ ldw 28(%r26), %r7
+ ldw 32(%r26), %r8
+ ldw 36(%r26), %r9
+ ldw 40(%r26), %r10
+ ldw 44(%r26), %r11
+ ldw 48(%r26), %r12
+ ldw 52(%r26), %r13
+ ldw 56(%r26), %r14
+ ldw 60(%r26), %r15
+ ldw 64(%r26), %r16
+ ldw 68(%r26), %r17
+ ldw 72(%r26), %r18
+ ldw 76(%r26), %r19
+ ldw 80(%r26), %r20
+ ldw 84(%r26), %r21
+ ldw 88(%r26), %r22
+ ldw 92(%r26), %r23
+ ldw 96(%r26), %r24
+ ldw 100(%r26), %r25
+ ldw 108(%r26), %r27
+ ldw 112(%r26), %r28
+ ldw 116(%r26), %r29
+ ldw 120(%r26), %r30
+ ldw 124(%r26), %r31
+ ldw 104(%r26), %r26
+ bv,n %r0(%r2)
+EXIT(_ZNK7_Unwind14Registers_HPPA6jumptoEv)
+#endif
+
+#ifdef __or1k__
+ENTRY_NP(_ZN7_Unwind14Registers_or1kC1Ev)
+ l.sw (0*3)(r3), r0
+ l.sw (1*3)(r3), r1
+ l.sw (2*3)(r3), r2
+ l.sw (3*3)(r3), r3
+ l.sw (4*3)(r3), r4
+ l.sw (5*3)(r3), r5
+ l.sw (6*3)(r3), r6
+ l.sw (7*3)(r3), r7
+ l.sw (8*3)(r3), r8
+ l.sw (9*3)(r3), r9
+ l.sw (10*3)(r3), r10
+ l.sw (11*3)(r3), r11
+ l.sw (12*3)(r3), r12
+ l.sw (13*3)(r3), r13
+ l.sw (14*3)(r3), r14
+ l.sw (15*3)(r3), r15
+ l.sw (16*3)(r3), r16
+ l.sw (17*3)(r3), r17
+ l.sw (18*3)(r3), r18
+ l.sw (19*3)(r3), r19
+ l.sw (20*3)(r3), r20
+ l.sw (21*3)(r3), r21
+ l.sw (22*3)(r3), r22
+ l.sw (23*3)(r3), r23
+ l.sw (24*3)(r3), r24
+ l.sw (25*3)(r3), r25
+ l.sw (26*3)(r3), r26
+ l.sw (27*3)(r3), r27
+ l.sw (28*3)(r3), r28
+ l.sw (29*3)(r3), r29
+ l.sw (30*3)(r3), r30
+ l.sw (31*3)(r3), r31
+ l.mfspr r4, r0, 20
+ l.sw (32*4)(r3), r4
+ l.jr lr
+ l.nop
+END(_ZN7_Unwind14Registers_or1kC1Ev)
+
+ENTRY_NP(_ZNK7_Unwind14Registers_or1k6jumptoEv)
+ l.lwz r6, (32*4)(r3)
+ l.mtspr r0, r6, 20
+ l.lwz r0, (0*4)(r3)
+ l.lwz r1, (1*4)(r3)
+ l.lwz r2, (2*4)(r3)
+ l.lwz r4, (4*4)(r3)
+ l.lwz r5, (5*4)(r3)
+ l.lwz r6, (6*4)(r3)
+ l.lwz r7, (7*4)(r3)
+ l.lwz r8, (8*4)(r3)
+ l.lwz r9, (9*4)(r3)
+ l.lwz r10, (10*4)(r3)
+ l.lwz r11, (11*4)(r3)
+ l.lwz r12, (12*4)(r3)
+ l.lwz r13, (13*4)(r3)
+ l.lwz r14, (14*4)(r3)
+ l.lwz r15, (15*4)(r3)
+ l.lwz r16, (16*4)(r3)
+ l.lwz r17, (17*4)(r3)
+ l.lwz r18, (18*4)(r3)
+ l.lwz r19, (19*4)(r3)
+ l.lwz r20, (20*4)(r3)
+ l.lwz r21, (21*4)(r3)
+ l.lwz r22, (22*4)(r3)
+ l.lwz r23, (23*4)(r3)
+ l.lwz r24, (24*4)(r3)
+ l.lwz r25, (25*4)(r3)
+ l.lwz r26, (26*4)(r3)
+ l.lwz r27, (27*4)(r3)
+ l.lwz r28, (28*4)(r3)
+ l.lwz r29, (29*4)(r3)
+ l.lwz r30, (30*4)(r3)
+ l.lwz r31, (31*4)(r3)
+
+ l.lwz r3, (3*4)(r3) /* return r3 */
+ l.jr lr
+END(_ZNK7_Unwind14Registers_or1k6jumptoEv)
+
+#endif
Index: gnu/lib/libgcc/Makefile
===================================================================
--- gnu/lib/libgcc/Makefile
+++ gnu/lib/libgcc/Makefile
@@ -3,8 +3,7 @@
GCCDIR= ${.CURDIR}/../../../contrib/gcc
GCCLIB= ${.CURDIR}/../../../contrib/gcclibs
COMPILERRTDIR= ${.CURDIR}/../../../contrib/compiler-rt
-UNWINDINCDIR= ${.CURDIR}/../../../contrib/llvm/projects/libunwind/include
-UNWINDSRCDIR= ${.CURDIR}/../../../contrib/llvm/projects/libunwind/src
+UNWINDSRCDIR= ${.CURDIR}/../../../contrib/netbsd-unwind
SHLIB_NAME= libgcc_s.so.1
SHLIBDIR?= /lib
@@ -78,15 +77,11 @@
.PATH: ${UNWINDSRCDIR}
LIB2ADDEH = gcc_personality_v0.c \
int_util.c \
- Unwind-EHABI.cpp \
- Unwind-sjlj.c \
- UnwindLevel1-gcc-ext.c \
- UnwindLevel1.c \
- UnwindRegistersRestore.S \
- UnwindRegistersSave.S \
- libunwind.cpp
-
-CFLAGS+= -I${UNWINDINCDIR} -I${.CURDIR}
+ libunwind.cxx \
+ rb.c \
+ unwind_registers.S
+
+CFLAGS+= -I${UNWINDSRCDIR} -I${.CURDIR}
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
Index: share/mk/src.opts.mk
===================================================================
--- share/mk/src.opts.mk
+++ share/mk/src.opts.mk
@@ -217,24 +217,23 @@
.if ${COMPILER_FEATURES:Mc++11} && (${__T} == "aarch64" || \
${__T} == "amd64" || ${__TT} == "arm" || ${__T} == "i386")
# Clang is enabled, and will be installed as the default /usr/bin/cc.
-__DEFAULT_YES_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
+__DEFAULT_YES_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC \
+ LLVM_LIBUNWIND
__DEFAULT_NO_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX
.elif ${COMPILER_FEATURES:Mc++11} && ${__T:Mpowerpc*}
# On powerpc, if an external compiler that supports C++11 is used as ${CC},
# then Clang is enabled, but GCC is installed as the default /usr/bin/cc.
__DEFAULT_YES_OPTIONS+=CLANG CLANG_FULL GCC GCC_BOOTSTRAP GNUCXX
-__DEFAULT_NO_OPTIONS+=CLANG_BOOTSTRAP CLANG_IS_CC
+__DEFAULT_NO_OPTIONS+=CLANG_BOOTSTRAP CLANG_IS_CC LLVM_LIBUNWIND
.else
# Everything else disables Clang, and uses GCC instead.
__DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX
-__DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
+__DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC \
+ LLVM_LIBUNWIND
.endif
# In-tree binutils/gcc are older versions without modern architecture support.
.if ${__T} == "aarch64" || ${__T} == "riscv64"
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
-__DEFAULT_YES_OPTIONS+=LLVM_LIBUNWIND
-.else
-__DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND
.endif
.if ${__T} == "riscv64"
BROKEN_OPTIONS+=PROFILE # "sorry, unimplemented: profiler support for RISC-V"

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 2, 12:18 AM (5 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30081404
Default Alt Text
D5929.1790900286.diff (582 KB)

Event Timeline