[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
This revision was automatically updated to reflect the committed changes. Closed by commit rL316747: Add support for dwarf unwinding on windows on x86_64 (authored by mstorsjo). Changed prior to commit: https://reviews.llvm.org/D38819?vs=120380=120552#toc Repository: rL LLVM https://reviews.llvm.org/D38819 Files: libunwind/trunk/docs/index.rst libunwind/trunk/include/__libunwind_config.h libunwind/trunk/include/libunwind.h libunwind/trunk/include/unwind.h libunwind/trunk/src/AddressSpace.hpp libunwind/trunk/src/Registers.hpp libunwind/trunk/src/UnwindLevel1.c libunwind/trunk/src/UnwindRegistersRestore.S libunwind/trunk/src/UnwindRegistersSave.S Index: libunwind/trunk/docs/index.rst === --- libunwind/trunk/docs/index.rst +++ libunwind/trunk/docs/index.rst @@ -52,6 +52,7 @@ Linuxi386, 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, x86_64 ClangDWARF CFI The following minimum compiler versions are strongly recommended. Index: libunwind/trunk/src/UnwindLevel1.c === --- libunwind/trunk/src/UnwindLevel1.c +++ libunwind/trunk/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: libunwind/trunk/src/Registers.hpp === --- libunwind/trunk/src/Registers.hpp +++ libunwind/trunk/src/Registers.hpp @@ -245,7 +245,7 @@ boolvalidFloatRegister(int) const { return false; } double getFloatRegister(int num) const; voidsetFloatRegister(int num, double value); - boolvalidVectorRegister(int) const { return false; } + boolvalidVectorRegister(int) const; v128getVectorRegister(int num) const; voidsetVectorRegister(int num, v128 value); const char *getRegisterName(int num); @@ -292,8 +292,14 @@ uint64_t __cs; uint64_t __fs; uint64_t __gs; +#if defined(_WIN64) +uint64_t __padding; // 16-byte align +#endif }; GPRs _registers; +#if defined(_WIN64) + v128 _xmm[16]; +#endif }; inline Registers_x86_64::Registers_x86_64(const void *registers) { @@ -458,6 +464,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 +509,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
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
rnk accepted this revision. rnk added a comment. This revision is now accepted and ready to land. lgtm https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo updated this revision to Diff 120380. mstorsjo added a comment. Simplified the assembly by sharing much more code between the unix and win64 paths, added a padding element to ensure more stable struct packing. https://reviews.llvm.org/D38819 Files: docs/index.rst include/__libunwind_config.h include/libunwind.h include/unwind.h src/AddressSpace.hpp src/Registers.hpp src/UnwindLevel1.c src/UnwindRegistersRestore.S src/UnwindRegistersSave.S Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -63,29 +63,56 @@ # 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 +#if defined(_WIN64) +#define PTR %rcx +#define TMP %rdx +#else +#define PTR %rdi +#define TMP %rsi +#endif + + movq %rax, (PTR) + movq %rbx, 8(PTR) + movq %rcx, 16(PTR) + movq %rdx, 24(PTR) + movq %rdi, 32(PTR) + movq %rsi, 40(PTR) + movq %rbp, 48(PTR) + movq %rsp, 56(PTR) + addq $8, 56(PTR) + movq %r8, 64(PTR) + movq %r9, 72(PTR) + movq %r10, 80(PTR) + movq %r11, 88(PTR) + movq %r12, 96(PTR) + movq %r13,104(PTR) + movq %r14,112(PTR) + movq %r15,120(PTR) + movq (%rsp),TMP + movq TMP,128(PTR) # store return address as rip # skip rflags # skip cs # skip fs # skip gs + +#if defined(_WIN64) + movdqu %xmm0,176(PTR) + movdqu %xmm1,192(PTR) + movdqu %xmm2,208(PTR) + movdqu %xmm3,224(PTR) + movdqu %xmm4,240(PTR) + movdqu %xmm5,256(PTR) + movdqu %xmm6,272(PTR) + movdqu %xmm7,288(PTR) + movdqu %xmm8,304(PTR) + movdqu %xmm9,320(PTR) + movdqu %xmm10,336(PTR) + movdqu %xmm11,352(PTR) + movdqu %xmm12,368(PTR) + movdqu %xmm13,384(PTR) + movdqu %xmm14,400(PTR) + movdqu %xmm15,416(PTR) +#endif xorl %eax, %eax# return UNW_ESUCCESS ret Index: src/UnwindRegistersRestore.S === --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -65,7 +65,16 @@ # # void libunwind::Registers_x86_64::jumpto() # +#if defined(_WIN64) +# On entry, thread_state pointer is in rcx; move it into rdi +# to share restore code below. Since this routine restores and +# overwrites all registers, we can use the same registers for +# pointers and temporaries as on unix even though win64 normally +# mustn't clobber some of them. + movq %rcx, %rdi +#else # On entry, thread_state pointer is in rdi +#endif movq 56(%rdi), %rax # rax holds new stack pointer subq $16, %rax @@ -95,6 +104,25 @@ # skip cs # skip fs # skip gs + +#if defined(_WIN64) + movdqu 176(%rdi),%xmm0 + movdqu 192(%rdi),%xmm1 + movdqu 208(%rdi),%xmm2 + movdqu 224(%rdi),%xmm3 + movdqu 240(%rdi),%xmm4 + movdqu 256(%rdi),%xmm5 + movdqu 272(%rdi),%xmm6 + movdqu 288(%rdi),%xmm7 + movdqu 304(%rdi),%xmm8 + movdqu 320(%rdi),%xmm9 + movdqu 336(%rdi),%xmm10 + movdqu 352(%rdi),%xmm11 + movdqu 368(%rdi),%xmm12 + movdqu 384(%rdi),%xmm13 + movdqu 400(%rdi),%xmm14 + movdqu 416(%rdi),%xmm15 +#endif movq 56(%rdi), %rsp # cut back rsp to new location pop%rdi # rdi was saved here earlier ret# rip was saved here 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/Registers.hpp === --- src/Registers.hpp +++ src/Registers.hpp @@ -245,12 +245,16 @@ boolvalidFloatRegister(int) const { return false; } double getFloatRegister(int num) const; voidsetFloatRegister(int
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: src/UnwindRegistersRestore.S:72 + movq 56(%rcx), %rax # rax holds new stack pointer + subq $16, %rax + movq %rax, 56(%rcx) mstorsjo wrote: > compnerd wrote: > > Hmm, why is this `$16`? The `$rsp` was adjusted by `$8` in the `setjmp`. > This is the exact same thing as is done right now for x86_64 on unixy systems > already, just with different registers. > > The adjustment by 16 bytes is because we store `rcx` and `rip` on the stack > here to restore them slightly differently than the others. See the `store new > rcx/rip on new stack`, `restore rcx later` and `rcx was saved here earlier` > and `rip was saved here` comments below. Instead of duplicating the asm for the win64 and unix calling convention, I can also pretty easily template it using the cpp, using a define for whatever register holds the context pointer from the first function argument. Would that be better, or is it clearer just to have it typed out in both forms literally? https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo updated this revision to Diff 120215. mstorsjo edited the summary of this revision. mstorsjo added a comment. Updated to take care of saving/restoring XMM registers as well. https://reviews.llvm.org/D38819 Files: docs/index.rst include/__libunwind_config.h include/libunwind.h include/unwind.h src/AddressSpace.hpp src/Registers.hpp src/UnwindLevel1.c src/UnwindRegistersRestore.S src/UnwindRegistersSave.S 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 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 + movq0(%rcx), %rax + movq8(%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/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/Registers.hpp === --- src/Registers.hpp +++ src/Registers.hpp @@ -245,12 +245,12 @@ boolvalidFloatRegister(int) const { return false; } double getFloatRegister(int num) const;
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: src/UnwindRegistersRestore.S:98 + # skip fs + # skip gs + movq 56(%rcx), %rsp # cut back rsp to new location rnk wrote: > mstorsjo wrote: > > mstorsjo wrote: > > > compnerd wrote: > > > > Doesn't Win64 ABI require some of the MMX registers be saved/restored > > > > too? > > > Right, yes, xmm6-xmm15 should be backed up and restored. I'll try to > > > amend this with such a change. > > Actually, such a change doesn't necessarily make much sense on its own. > > > > As long as the dwarf encoding itself doesn't describe how to restore those > > registers (and on unix platforms you don't need to, so it probably isn't > > even specified), you'd just end up backing up the xmm registers on entry > > when throwing the exception, and restoring the exactly same ones again - it > > only guards against changes within libcxxabi/libunwind and the unwinding > > machinery itself, not against changes further down in the call stack > > between the thrower and catcher of the exception. > > > > So with that, I guess this patch is futile unless planning to extend the > > x86_64 dwarf handling in llvm to include those registers as well - and > > that's a little out of scope of what I intended to do here... > If we have XMM values in the register context, we might as well reload them > here. I assume libunwind will switch away from DWARF and over to UNWIND_INFO > opcodes in the near future, and that will give us an accurate register > context. Yeah, although to do anything useful with the XMM registers, the llvm backend would have to output dwarf opcodes for callee saved xmm registers, which it currently doesn't. Otherwise it'll just reload them back to the same values as they already are. I've managed to hack LLVM to do that (without fully understanding what I'm doing though), and I'll see if I manage to update libunwind to use that as well. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
rnk added inline comments. Comment at: src/UnwindRegistersRestore.S:98 + # skip fs + # skip gs + movq 56(%rcx), %rsp # cut back rsp to new location mstorsjo wrote: > mstorsjo wrote: > > compnerd wrote: > > > Doesn't Win64 ABI require some of the MMX registers be saved/restored too? > > Right, yes, xmm6-xmm15 should be backed up and restored. I'll try to amend > > this with such a change. > Actually, such a change doesn't necessarily make much sense on its own. > > As long as the dwarf encoding itself doesn't describe how to restore those > registers (and on unix platforms you don't need to, so it probably isn't even > specified), you'd just end up backing up the xmm registers on entry when > throwing the exception, and restoring the exactly same ones again - it only > guards against changes within libcxxabi/libunwind and the unwinding machinery > itself, not against changes further down in the call stack between the > thrower and catcher of the exception. > > So with that, I guess this patch is futile unless planning to extend the > x86_64 dwarf handling in llvm to include those registers as well - and that's > a little out of scope of what I intended to do here... If we have XMM values in the register context, we might as well reload them here. I assume libunwind will switch away from DWARF and over to UNWIND_INFO opcodes in the near future, and that will give us an accurate register context. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: src/UnwindRegistersRestore.S:98 + # skip fs + # skip gs + movq 56(%rcx), %rsp # cut back rsp to new location mstorsjo wrote: > compnerd wrote: > > Doesn't Win64 ABI require some of the MMX registers be saved/restored too? > Right, yes, xmm6-xmm15 should be backed up and restored. I'll try to amend > this with such a change. Actually, such a change doesn't necessarily make much sense on its own. As long as the dwarf encoding itself doesn't describe how to restore those registers (and on unix platforms you don't need to, so it probably isn't even specified), you'd just end up backing up the xmm registers on entry when throwing the exception, and restoring the exactly same ones again - it only guards against changes within libcxxabi/libunwind and the unwinding machinery itself, not against changes further down in the call stack between the thrower and catcher of the exception. So with that, I guess this patch is futile unless planning to extend the x86_64 dwarf handling in llvm to include those registers as well - and that's a little out of scope of what I intended to do here... https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: src/UnwindRegistersRestore.S:98 + # skip fs + # skip gs + movq 56(%rcx), %rsp # cut back rsp to new location compnerd wrote: > Doesn't Win64 ABI require some of the MMX registers be saved/restored too? Right, yes, xmm6-xmm15 should be backed up and restored. I'll try to amend this with such a change. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
compnerd added inline comments. Comment at: src/UnwindRegistersRestore.S:98 + # skip fs + # skip gs + movq 56(%rcx), %rsp # cut back rsp to new location Doesn't Win64 ABI require some of the MMX registers be saved/restored too? https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added a comment. Ping https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: docs/index.rst:55 NetBSD x86_64 Clang, GCC DWARF CFI -Windows i386 ClangDWARF CFI +Windows i386, x86_64 ClangDWARF CFI martell wrote: > Based on your comments above I assume this supports GCC also ? > If so, replace > `Windows i386, x86_64 ClangDWARF CFI` > with > `Windows i386, x86_64 Clang, GCC DWARF CFI` > > This is exciting stuff Martin :) I'm not sure if gcc supports dwarf exceptions on x86_64 or how much hacking is needed to enable it; the comment about gcc for `__SIZEOF_POINTER__` was because it was in generic code that could be used by gcc in one of the existing cases where gcc actually is supported. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
martell added inline comments. Comment at: docs/index.rst:55 NetBSD x86_64 Clang, GCC DWARF CFI -Windows i386 ClangDWARF CFI +Windows i386, x86_64 ClangDWARF CFI Based on your comments above I assume this supports GCC also ? If so, replace `Windows i386, x86_64 ClangDWARF CFI` with `Windows i386, x86_64 Clang, GCC DWARF CFI` This is exciting stuff Martin :) https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo updated this revision to Diff 119068. mstorsjo added a comment. Use `__SIZEOF_POINTER__` instead of checking `__LP64__` together with `_WIN64`. Changed `_WIN32` into `_WIN64` within the assembly sources for consistency/clarity. Removed one type definition ifdef by just using `(u)intptr_t` instead. https://reviews.llvm.org/D38819 Files: docs/index.rst include/unwind.h src/AddressSpace.hpp src/UnwindLevel1.c src/UnwindRegistersRestore.S src/UnwindRegistersSave.S Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -63,6 +63,27 @@ # 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 +#else movq %rax, (%rdi) movq %rbx, 8(%rdi) movq %rcx, 16(%rdi) @@ -82,6 +103,7 @@ movq %r15,120(%rdi) movq (%rsp),%rsi movq %rsi,128(%rdi) # store return address as rip +#endif # skip rflags # skip cs # skip fs Index: src/UnwindRegistersRestore.S === --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -65,6 +65,40 @@ # # 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 + movq0(%rcx), %rax + movq8(%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 + 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 +131,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/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/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(, (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: 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
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added inline comments. Comment at: include/unwind.h:125 uintptr_t private_2; // holds sp that phase1 found for phase2 to use -#ifndef __LP64__ +#if !defined(__LP64__) && !defined(_WIN64) // The implementation of _Unwind_Exception uses an attribute mode on the compnerd wrote: > I think I would prefer that we do this generically as: > > #if __POINTER_WIDTH__ == 32 It seems like GCC doesn't set `__POINTER_WIDTH__`, but both GCC and clang set `__SIZEOF_POINTER__`, so I can use that. Comment at: src/AddressSpace.hpp:145 public: -#ifdef __LP64__ +#if defined(__LP64__) || defined(_WIN64) typedef uint64_t pint_t; compnerd wrote: > I think I prefer the generic: > > #if __POINTER_WIDTH__ == 64 This one probably could be simplified even further by just using `intptr_t` and `uintptr_t`, right? Comment at: src/UnwindRegistersRestore.S:68 # +#if defined(_WIN32) +# On entry, thread_state pointer is in rcx compnerd wrote: > This is confusing. Why is this `_WIN32`? Shouldn't this be `_WIN64`? I guess I could use that as well. I just used `_WIN32` out of habit as generic identifier for windows-in-whatever-form; both `_WIN32` and `_WIN64` are defined, and we're within an `#ifdef __x86_64__` anyway. I can change it into `_WIN64` for clarity. Comment at: src/UnwindRegistersRestore.S:72 + movq 56(%rcx), %rax # rax holds new stack pointer + subq $16, %rax + movq %rax, 56(%rcx) compnerd wrote: > Hmm, why is this `$16`? The `$rsp` was adjusted by `$8` in the `setjmp`. This is the exact same thing as is done right now for x86_64 on unixy systems already, just with different registers. The adjustment by 16 bytes is because we store `rcx` and `rip` on the stack here to restore them slightly differently than the others. See the `store new rcx/rip on new stack`, `restore rcx later` and `rcx was saved here earlier` and `rip was saved here` comments below. Comment at: src/UnwindRegistersSave.S:66 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if defined(_WIN32) + movq %rax, (%rcx) compnerd wrote: > Shouldn't this be `_WIN64`? Same as the otherone; we're within `#ifdef __x86_64__`, but I can change it into `_WIN64` for clarity. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
compnerd added inline comments. Comment at: include/unwind.h:125 uintptr_t private_2; // holds sp that phase1 found for phase2 to use -#ifndef __LP64__ +#if !defined(__LP64__) && !defined(_WIN64) // The implementation of _Unwind_Exception uses an attribute mode on the I think I would prefer that we do this generically as: #if __POINTER_WIDTH__ == 32 Comment at: src/AddressSpace.hpp:145 public: -#ifdef __LP64__ +#if defined(__LP64__) || defined(_WIN64) typedef uint64_t pint_t; I think I prefer the generic: #if __POINTER_WIDTH__ == 64 Comment at: src/AddressSpace.hpp:197 inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#ifdef __LP64__ +#if defined(__LP64__) || defined(_WIN64) return get64(addr); Same. Comment at: src/UnwindRegistersRestore.S:68 # +#if defined(_WIN32) +# On entry, thread_state pointer is in rcx This is confusing. Why is this `_WIN32`? Shouldn't this be `_WIN64`? Comment at: src/UnwindRegistersRestore.S:72 + movq 56(%rcx), %rax # rax holds new stack pointer + subq $16, %rax + movq %rax, 56(%rcx) Hmm, why is this `$16`? The `$rsp` was adjusted by `$8` in the `setjmp`. Comment at: src/UnwindRegistersSave.S:66 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if defined(_WIN32) + movq %rax, (%rcx) Shouldn't this be `_WIN64`? https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo added a comment. As further explanation/justification - libcxxabi and libunwind don't support SEH exceptions yet. https://reviews.llvm.org/D38819 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D38819: [libunwind] Add support for dwarf unwinding on windows on x86_64
mstorsjo created this revision. Herald added a subscriber: aprantl. Clang doesn't currently support building for windows/x86_64 with dwarf by setting command line parameters, but if manually modified to use dwarf, we can make libunwind work in this configuration as well. Even if support for this is deemed pointless, I guess one could omit the assembly changes, but the fixes for the generic code probably are worthwhile at least. https://reviews.llvm.org/D38819 Files: docs/index.rst include/unwind.h src/AddressSpace.hpp src/UnwindLevel1.c src/UnwindRegistersRestore.S src/UnwindRegistersSave.S Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -63,6 +63,27 @@ # thread_state pointer is in rdi # DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) +#if defined(_WIN32) + 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 +#else movq %rax, (%rdi) movq %rbx, 8(%rdi) movq %rcx, 16(%rdi) @@ -82,6 +103,7 @@ movq %r15,120(%rdi) movq (%rsp),%rsi movq %rsi,128(%rdi) # store return address as rip +#endif # skip rflags # skip cs # skip fs Index: src/UnwindRegistersRestore.S === --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -65,6 +65,40 @@ # # void libunwind::Registers_x86_64::jumpto() # +#if defined(_WIN32) +# 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 + movq0(%rcx), %rax + movq8(%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 + 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 +131,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/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/AddressSpace.hpp === --- src/AddressSpace.hpp +++ src/AddressSpace.hpp @@ -142,7 +142,7 @@ /// making local unwinds fast. class __attribute__((visibility("hidden"))) LocalAddressSpace { public: -#ifdef __LP64__ +#if defined(__LP64__) || defined(_WIN64) typedef uint64_t pint_t; typedef int64_t sint_t; #else @@ -194,7 +194,7 @@ }; inline uintptr_t LocalAddressSpace::getP(pint_t addr) { -#ifdef __LP64__ +#if defined(__LP64__) || defined(_WIN64) return get64(addr); #else return get32(addr); 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