libc/setjump: Align stack at 16-bytes before function call
authorJohn Marino <draco@marino.st>
Tue, 11 Nov 2014 12:58:14 +0000 (13:58 +0100)
committerJohn Marino <draco@marino.st>
Tue, 11 Nov 2014 14:18:24 +0000 (15:18 +0100)
This is required by amd64 ABI.  Comments were added where stack was
"accidentally" properly aligned.  The problem manifested on with a
bus error when built by clang.

While here, preserve the floating float exceptions flags.  Per POSIX,
siglongjump() shall be equivalent to longjump() except that it must
match sigsetjump() instead of setjump() and except for the effect on the
signal mask.  Therefore it should preserve the FP exception flags.

Also add the GNU-stack notes, all libc object files are supposed to have
them (although I am pretty sure they don't).

Taken from:
FreeBSD svn 217106 (7 Jan 2011)
FreeBSD svn 227023 (2 Nov 2011)
FreeBSD svn 267307 (9 Jun 2014)

lib/libc/x86_64/gen/setjmp.S
lib/libc/x86_64/gen/sigsetjmp.S

index f22bd55..e8d0fa3 100644 (file)
@@ -53,6 +53,7 @@ ENTRY(setjmp)
        movq    $1,%rdi                 /* SIG_BLOCK       */
        movq    $0,%rsi                 /* (sigset_t*)set  */
        leaq    72(%rcx),%rdx           /* 9,10; (sigset_t*)oset */
+       /* stack is 16-byte aligned */
        call    PIC_PLT(CNAME(_sigprocmask))
        popq    %rdi
        movq    %rdi,%rcx
@@ -80,7 +81,9 @@ ENTRY(__longjmp)
        movq    $3,%rdi                 /* SIG_SETMASK     */
        leaq    72(%rdx),%rsi           /* (sigset_t*)set  */
        movq    $0,%rdx                 /* (sigset_t*)oset */
+       subq    $0x8,%rsp               /* make the stack 16-byte aligned */
        call    PIC_PLT(CNAME(_sigprocmask))
+       addq    $0x8,%rsp
        popq    %rsi
        popq    %rdi                    /* jmpbuf */
        movq    %rdi,%rdx
@@ -109,3 +112,5 @@ ENTRY(__longjmp)
 1:     movq    %rcx,0(%rsp)
        ret
 END(__longjmp)
+
+       .section .note.GNU-stack,"",%progbits
index 6463634..9ca65be 100644 (file)
@@ -58,6 +58,7 @@ ENTRY(sigsetjmp)
        movq    $1,%rdi                 /* SIG_BLOCK       */
        movq    $0,%rsi                 /* (sigset_t*)set  */
        leaq    72(%rcx),%rdx           /* 9,10 (sigset_t*)oset */
+       /* stack is 16-byte aligned */
        call    PIC_PLT(CNAME(_sigprocmask))
        popq    %rdi
 2:     movq    %rdi,%rcx
@@ -86,7 +87,9 @@ ENTRY(__siglongjmp)
        movq    $3,%rdi                 /* SIG_SETMASK     */
        leaq    72(%rdx),%rsi           /* (sigset_t*)set  */
        movq    $0,%rdx                 /* (sigset_t*)oset */
+       subq    $0x8,%rsp               /* make the stack 16-byte aligned */
        call    PIC_PLT(CNAME(_sigprocmask))
+       addq    $0x8,%rsp
        popq    %rsi
        popq    %rdi                    /* jmpbuf */
 2:     movq    %rdi,%rdx
@@ -99,7 +102,6 @@ ENTRY(__siglongjmp)
        movq    40(%rdx),%r13
        movq    48(%rdx),%r14
        movq    56(%rdx),%r15
-       fninit
        fldcw   64(%rdx)
        testq   %rax,%rax
        jnz     1f
@@ -107,3 +109,5 @@ ENTRY(__siglongjmp)
 1:     movq    %rcx,0(%rsp)
        ret
 END(__siglongjmp)
+
+       .section .note.GNU-stack,"",%progbits