Index: docs/index.rst =================================================================== --- docs/index.rst +++ docs/index.rst @@ -52,7 +52,7 @@ Linux i386, x86_64, ARM64 Clang, GCC DWARF CFI Mac OS X i386, x86_64 Clang, GCC DWARF CFI NetBSD x86_64 Clang, GCC DWARF CFI -Windows i386 Clang DWARF CFI +Windows i386, x86_64 Clang DWARF CFI ============ ==================== ============ ======================== The following minimum compiler versions are strongly recommended. Index: include/__libunwind_config.h =================================================================== --- include/__libunwind_config.h +++ include/__libunwind_config.h @@ -23,9 +23,15 @@ # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 9 # elif defined(__x86_64__) # define _LIBUNWIND_TARGET_X86_64 1 -# define _LIBUNWIND_CONTEXT_SIZE 21 -# define _LIBUNWIND_CURSOR_SIZE 33 -# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 17 +# if defined(_WIN64) +# define _LIBUNWIND_CONTEXT_SIZE 53 +# define _LIBUNWIND_CURSOR_SIZE 65 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 33 +# else +# define _LIBUNWIND_CONTEXT_SIZE 21 +# define _LIBUNWIND_CURSOR_SIZE 33 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 17 +# endif # elif defined(__ppc__) # define _LIBUNWIND_TARGET_PPC 1 # define _LIBUNWIND_CONTEXT_SIZE 117 Index: include/libunwind.h =================================================================== --- include/libunwind.h +++ include/libunwind.h @@ -191,7 +191,24 @@ UNW_X86_64_R12 = 12, UNW_X86_64_R13 = 13, UNW_X86_64_R14 = 14, - UNW_X86_64_R15 = 15 + UNW_X86_64_R15 = 15, + UNW_X86_64_RIP = 16, + UNW_X86_64_XMM0 = 17, + UNW_X86_64_XMM1 = 18, + UNW_X86_64_XMM2 = 19, + UNW_X86_64_XMM3 = 20, + UNW_X86_64_XMM4 = 21, + UNW_X86_64_XMM5 = 22, + UNW_X86_64_XMM6 = 23, + UNW_X86_64_XMM7 = 24, + UNW_X86_64_XMM8 = 25, + UNW_X86_64_XMM9 = 26, + UNW_X86_64_XMM10 = 27, + UNW_X86_64_XMM11 = 28, + UNW_X86_64_XMM12 = 29, + UNW_X86_64_XMM13 = 30, + UNW_X86_64_XMM14 = 31, + UNW_X86_64_XMM15 = 32, }; Index: include/unwind.h =================================================================== --- include/unwind.h +++ include/unwind.h @@ -122,7 +122,7 @@ _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__ +#if __SIZEOF_POINTER__ == 4 // The implementation of _Unwind_Exception uses an attribute mode on the // above fields which has the side effect of causing this whole struct to // round up to 32 bytes in size. To be more explicit, we add pad fields Index: src/AddressSpace.hpp =================================================================== --- src/AddressSpace.hpp +++ src/AddressSpace.hpp @@ -142,13 +142,8 @@ /// 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 + typedef uintptr_t pint_t; + typedef intptr_t sint_t; uint8_t get8(pint_t addr) { uint8_t val; memcpy(&val, (void *)addr, sizeof(val)); @@ -194,7 +189,7 @@ }; inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#ifdef __LP64__ +#if __SIZEOF_POINTER__ == 8 return get64(addr); #else return get32(addr); Index: src/Registers.hpp =================================================================== --- src/Registers.hpp +++ src/Registers.hpp @@ -245,12 +245,12 @@ bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); - bool validVectorRegister(int) const { return false; } + bool validVectorRegister(int) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); const char *getRegisterName(int num); void jumpto(); - static int lastDwarfRegNum() { return 16; } + static int lastDwarfRegNum() { return 32; } uint64_t getSP() const { return _registers.__rsp; } void setSP(uint64_t value) { _registers.__rsp = value; } @@ -294,6 +294,9 @@ uint64_t __gs; }; GPRs _registers; +#if defined(_WIN64) + v128 _xmm[16]; +#endif }; inline Registers_x86_64::Registers_x86_64(const void *registers) { @@ -458,6 +461,38 @@ return "r14"; case UNW_X86_64_R15: return "r15"; + case UNW_X86_64_XMM0: + return "xmm0"; + case UNW_X86_64_XMM1: + return "xmm1"; + case UNW_X86_64_XMM2: + return "xmm2"; + case UNW_X86_64_XMM3: + return "xmm3"; + case UNW_X86_64_XMM4: + return "xmm4"; + case UNW_X86_64_XMM5: + return "xmm5"; + case UNW_X86_64_XMM6: + return "xmm6"; + case UNW_X86_64_XMM7: + return "xmm7"; + case UNW_X86_64_XMM8: + return "xmm8"; + case UNW_X86_64_XMM9: + return "xmm9"; + case UNW_X86_64_XMM10: + return "xmm10"; + case UNW_X86_64_XMM11: + return "xmm11"; + case UNW_X86_64_XMM12: + return "xmm12"; + case UNW_X86_64_XMM13: + return "xmm13"; + case UNW_X86_64_XMM14: + return "xmm14"; + case UNW_X86_64_XMM15: + return "xmm15"; default: return "unknown register"; } @@ -471,12 +506,34 @@ _LIBUNWIND_ABORT("no x86_64 float registers"); } -inline v128 Registers_x86_64::getVectorRegister(int) const { +inline bool Registers_x86_64::validVectorRegister(int regNum) const { +#if defined(_WIN64) + if (regNum < UNW_X86_64_XMM0) + return false; + if (regNum > UNW_X86_64_XMM15) + return false; + return true; +#else + return false; +#endif +} + +inline v128 Registers_x86_64::getVectorRegister(int regNum) const { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + return _xmm[regNum - UNW_X86_64_XMM0]; +#else _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif } -inline void Registers_x86_64::setVectorRegister(int, v128) { +inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { +#if defined(_WIN64) + assert(validVectorRegister(regNum)); + _xmm[regNum - UNW_X86_64_XMM0] = value; +#else _LIBUNWIND_ABORT("no x86_64 vector registers"); +#endif } #endif // _LIBUNWIND_TARGET_X86_64 Index: src/UnwindLevel1.c =================================================================== --- src/UnwindLevel1.c +++ src/UnwindLevel1.c @@ -86,7 +86,7 @@ // this frame. if (frameInfo.handler != 0) { __personality_routine p = - (__personality_routine)(long)(frameInfo.handler); + (__personality_routine)(uintptr_t)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( "unwind_phase1(ex_ojb=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); @@ -181,7 +181,7 @@ // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { __personality_routine p = - (__personality_routine)(long)(frameInfo.handler); + (__personality_routine)(uintptr_t)(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. Index: src/UnwindRegistersRestore.S =================================================================== --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -65,6 +65,56 @@ # # void libunwind::Registers_x86_64::jumpto() # +#if defined(_WIN64) +# On entry, thread_state pointer is in rcx + + movq 56(%rcx), %rax # rax holds new stack pointer + subq $16, %rax + movq %rax, 56(%rcx) + movq 16(%rcx), %rdx # store new rcx on new stack + movq %rdx, 0(%rax) + movq 128(%rcx), %rdx # store new rip on new stack + movq %rdx, 8(%rax) + # restore all registers + movq 0(%rcx), %rax + movq 8(%rcx), %rbx + # restore rcx later + movq 24(%rcx), %rdx + movq 32(%rcx), %rdi + movq 40(%rcx), %rsi + movq 48(%rcx), %rbp + # restore rsp later + movq 64(%rcx), %r8 + movq 72(%rcx), %r9 + movq 80(%rcx), %r10 + movq 88(%rcx), %r11 + movq 96(%rcx), %r12 + movq 104(%rcx), %r13 + movq 112(%rcx), %r14 + movq 120(%rcx), %r15 + # skip rflags + # skip cs + # skip fs + # skip gs + movdqu 168(%rcx),%xmm0 + movdqu 184(%rcx),%xmm1 + movdqu 200(%rcx),%xmm2 + movdqu 216(%rcx),%xmm3 + movdqu 232(%rcx),%xmm4 + movdqu 248(%rcx),%xmm5 + movdqu 264(%rcx),%xmm6 + movdqu 280(%rcx),%xmm7 + movdqu 296(%rcx),%xmm8 + movdqu 312(%rcx),%xmm9 + movdqu 328(%rcx),%xmm10 + movdqu 344(%rcx),%xmm11 + movdqu 360(%rcx),%xmm12 + movdqu 376(%rcx),%xmm13 + movdqu 392(%rcx),%xmm14 + movdqu 408(%rcx),%xmm15 + movq 56(%rcx), %rsp # cut back rsp to new location + pop %rcx # rcx was saved here earlier +#else # On entry, thread_state pointer is in rdi movq 56(%rdi), %rax # rax holds new stack pointer @@ -97,6 +147,7 @@ # skip gs movq 56(%rdi), %rsp # cut back rsp to new location pop %rdi # rdi was saved here earlier +#endif ret # rip was saved here Index: src/UnwindRegistersSave.S =================================================================== --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -63,6 +63,43 @@ # thread_state pointer is in rdi # DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if defined(_WIN64) + movq %rax, (%rcx) + movq %rbx, 8(%rcx) + movq %rcx, 16(%rcx) + movq %rdx, 24(%rcx) + movq %rdi, 32(%rcx) + movq %rsi, 40(%rcx) + movq %rbp, 48(%rcx) + movq %rsp, 56(%rcx) + addq $8, 56(%rcx) + movq %r8, 64(%rcx) + movq %r9, 72(%rcx) + movq %r10, 80(%rcx) + movq %r11, 88(%rcx) + movq %r12, 96(%rcx) + movq %r13,104(%rcx) + movq %r14,112(%rcx) + movq %r15,120(%rcx) + movq (%rsp),%rdx + movq %rdx,128(%rcx) # store return address as rip + movdqu %xmm0,168(%rcx) + movdqu %xmm1,184(%rcx) + movdqu %xmm2,200(%rcx) + movdqu %xmm3,216(%rcx) + movdqu %xmm4,232(%rcx) + movdqu %xmm5,248(%rcx) + movdqu %xmm6,264(%rcx) + movdqu %xmm7,280(%rcx) + movdqu %xmm8,296(%rcx) + movdqu %xmm9,312(%rcx) + movdqu %xmm10,328(%rcx) + movdqu %xmm11,344(%rcx) + movdqu %xmm12,360(%rcx) + movdqu %xmm13,376(%rcx) + movdqu %xmm14,392(%rcx) + movdqu %xmm15,408(%rcx) +#else movq %rax, (%rdi) movq %rbx, 8(%rdi) movq %rcx, 16(%rdi) @@ -82,6 +119,7 @@ movq %r15,120(%rdi) movq (%rsp),%rsi movq %rsi,128(%rdi) # store return address as rip +#endif # skip rflags # skip cs # skip fs