@@ -19,7 +19,7 @@
#include <jmpbuf-offsets.h>
#include <asm-syntax.h>
#include <stap-probe.h>
-
+#include <jmp_buf-ssp.h>
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
@@ -46,6 +46,40 @@ longjmp_msg:
ENTRY (____longjmp_chk)
movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ xorl %edx, %edx
+ /* Get the current ssp. */
+ rdsspd %edx
+ /* And compare it with the saved ssp value. */
+ subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+ je .Lnoadj
+ /* Count the number of frames to adjust and adjust it
+ with incssp instruction. The instruction can adjust
+ the ssp by [0..255] value only thus use a loop if
+ the number of frames is bigger than 255. */
+ negl %edx
+ shrl $2, %edx
+ /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
+ restoring Shadow-Stack-Pointer of setjmp's caller, we
+ need to unwind shadow stack by one more frame. */
+ addl $1, %edx
+ cmpl $255, %edx
+ jbe .Lonetime
+.Loopadj:
+ incsspd %edx
+ subl $255, %edx
+ cmpl $255, %edx
+ ja .Loopadj
+.Lonetime:
+ incsspd %edx
+.Lnoadj:
+#endif
/* Save the return address now. */
movl (JB_PC*4)(%ecx), %edx
/* Get the stack pointer. */
new file mode 100644
@@ -0,0 +1,141 @@
+/* longjmp for Linux/i386 with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+ .text
+ENTRY (__longjmp)
+#ifdef PTR_DEMANGLE
+ movl 4(%esp), %eax /* User's jmp_buf in %eax. */
+
+# ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ xorl %edx, %edx
+ /* Get the current ssp. */
+ rdsspd %edx
+ /* And compare it with the saved ssp value. */
+ subl SHADOW_STACK_POINTER_OFFSET(%eax), %edx
+ je .Lnoadj
+ /* Count the number of frames to adjust and adjust it
+ with incssp instruction. The instruction can adjust
+ the ssp by [0..255] value only thus use a loop if
+ the number of frames is bigger than 255. */
+ negl %edx
+ shrl $2, %edx
+ /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
+ restoring Shadow-Stack-Pointer of setjmp's caller, we
+ need to unwind shadow stack by one more frame. */
+ addl $1, %edx
+ cmpl $255, %edx
+ jbe .Lonetime
+.Loopadj:
+ incsspd %edx
+ subl $255, %edx
+ cmpl $255, %edx
+ ja .Loopadj
+.Lonetime:
+ incsspd %edx
+.Lnoadj:
+# endif
+ /* Save the return address now. */
+ movl (JB_PC*4)(%eax), %edx
+ /* Get the stack pointer. */
+ movl (JB_SP*4)(%eax), %ecx
+ PTR_DEMANGLE (%edx)
+ PTR_DEMANGLE (%ecx)
+ LIBC_PROBE (longjmp, 3, 4@%eax, -4@8(%esp), 4@%edx)
+ cfi_def_cfa(%eax, 0)
+ cfi_register(%eip, %edx)
+ cfi_register(%esp, %ecx)
+ cfi_offset(%ebx, JB_BX*4)
+ cfi_offset(%esi, JB_SI*4)
+ cfi_offset(%edi, JB_DI*4)
+ cfi_offset(%ebp, JB_BP*4)
+ /* Restore registers. */
+ movl (JB_BX*4)(%eax), %ebx
+ movl (JB_SI*4)(%eax), %esi
+ movl (JB_DI*4)(%eax), %edi
+ movl (JB_BP*4)(%eax), %ebp
+ cfi_restore(%ebx)
+ cfi_restore(%esi)
+ cfi_restore(%edi)
+ cfi_restore(%ebp)
+
+ LIBC_PROBE (longjmp_target, 3, 4@%eax, -4@8(%esp), 4@%edx)
+ movl 8(%esp), %eax /* Second argument is return value. */
+ movl %ecx, %esp
+#else
+ movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
+ movl 8(%esp), %eax /* Second argument is return value. */
+# ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ xorl %edx, %edx
+ /* Get the current ssp. */
+ rdsspd %edx
+ /* And compare it with the saved ssp value. */
+ subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
+ je .Lnoadj
+ /* Count the number of frames to adjust and adjust it
+ with incssp instruction. The instruction can adjust
+ the ssp by [0..255] value only thus use a loop if
+ the number of frames is bigger than 255. */
+ negl %edx
+ shrl $2, %edx
+ /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
+ restoring Shadow-Stack-Pointer of setjmp's caller, we
+ need to unwind shadow stack by one more frame. */
+ addl $1, %edx
+ cmpl $255, %edx
+ jbe .Lonetime
+.Loopadj:
+ incsspd %edx
+ subl $255, %edx
+ cmpl $255, %edx
+ ja .Loopadj
+.Lonetime:
+ incsspd %edx
+.Lnoadj:
+# endif
+ /* Save the return address now. */
+ movl (JB_PC*4)(%ecx), %edx
+ LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
+ /* Restore registers. */
+ movl (JB_BX*4)(%ecx), %ebx
+ movl (JB_SI*4)(%ecx), %esi
+ movl (JB_DI*4)(%ecx), %edi
+ movl (JB_BP*4)(%ecx), %ebp
+ movl (JB_SP*4)(%ecx), %esp
+ LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%ecx, 4@%edx)
+#endif
+ /* Jump to saved PC. */
+ jmp *%edx
+END (__longjmp)
new file mode 100644
@@ -0,0 +1,72 @@
+/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. Linux/i386 version
+ with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS 4 /* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+4
+
+ENTRY (_setjmp)
+
+ xorl %eax, %eax
+ movl JMPBUF(%esp), %edx
+
+ /* Save registers. */
+ movl %ebx, (JB_BX*4)(%edx)
+ movl %esi, (JB_SI*4)(%edx)
+ movl %edi, (JB_DI*4)(%edx)
+ leal JMPBUF(%esp), %ecx /* Save SP as it will be after we return. */
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_SP*4)(%edx)
+ movl 0(%esp), %ecx /* Save PC we are returning to now. */
+ LIBC_PROBE (setjmp, 3, 4@%edx, -4@$0, 4@%ecx)
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_PC*4)(%edx)
+ movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer. */
+
+ movl %eax, JB_SIZE(%edx) /* No signal mask set. */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_ssp
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ xorl %ecx, %ecx
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%edx)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+ ret
+END (_setjmp)
+libc_hidden_def (_setjmp)
new file mode 100644
@@ -0,0 +1,82 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. Linux/i386 version
+ with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS 4 /* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+4
+
+ENTRY (setjmp)
+ /* Note that we have to use a non-exported symbol in the next
+ jump since otherwise gas will emit it as a jump through the
+ PLT which is what we cannot use here. */
+
+ movl JMPBUF(%esp), %eax
+
+ /* Save registers. */
+ movl %ebx, (JB_BX*4)(%eax)
+ movl %esi, (JB_SI*4)(%eax)
+ movl %edi, (JB_DI*4)(%eax)
+ leal JMPBUF(%esp), %ecx /* Save SP as it will be after we return. */
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_SP*4)(%eax)
+ movl 0(%esp), %ecx /* Save PC we are returning to now. */
+ LIBC_PROBE (setjmp, 3, 4@%eax, -4@$1, 4@%ecx)
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_PC*4)(%eax)
+ movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_ssp
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ xorl %ecx, %ecx
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+
+ /* Call __sigjmp_save. */
+ pushl $1
+ cfi_adjust_cfa_offset (4)
+ pushl 8(%esp)
+ cfi_adjust_cfa_offset (4)
+ call __sigjmp_save
+ popl %ecx
+ cfi_adjust_cfa_offset (-4)
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ ret
+END (setjmp)
new file mode 100644
@@ -0,0 +1,73 @@
+/* setjmp for Linux/i386 with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+#define PARMS 4 /* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+4
+
+ENTRY (__sigsetjmp)
+
+ movl JMPBUF(%esp), %eax
+
+ /* Save registers. */
+ movl %ebx, (JB_BX*4)(%eax)
+ movl %esi, (JB_SI*4)(%eax)
+ movl %edi, (JB_DI*4)(%eax)
+ leal JMPBUF(%esp), %ecx /* Save SP as it will be after we return. */
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_SP*4)(%eax)
+ movl 0(%esp), %ecx /* Save PC we are returning to now. */
+ LIBC_PROBE (setjmp, 3, 4@%eax, -4@SIGMSK(%esp), 4@%ecx)
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%ecx)
+#endif
+ movl %ecx, (JB_PC*4)(%eax)
+ movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer. */
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %gs:FEATURE_1_OFFSET
+ jz .Lskip_ssp
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ xorl %ecx, %ecx
+ rdsspd %ecx
+ movl %ecx, SHADOW_STACK_POINTER_OFFSET(%eax)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+ /* In ld.so we never save the signal mask. */
+ xorl %eax, %eax
+ ret
+#else
+ /* Make a tail call to __sigjmp_save; it takes the same args. */
+ jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)
@@ -21,6 +21,7 @@
#include <stap-probe.h>
#include <sigaltstack-offsets.h>
+#include <jmp_buf-ssp.h>
.section .rodata.str1.1,"aMS",@progbits,1
.type longjmp_msg,@object
@@ -105,6 +106,40 @@ ENTRY(____longjmp_chk)
cfi_restore (%rsi)
.Lok:
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ xorq %rax, %rax
+ /* Get the current ssp. */
+ rdsspq %rax
+ /* And compare it with the saved ssp value. */
+ subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+ je .Lnoadj
+ /* Count the number of frames to adjust and adjust it
+ with incssp instruction. The instruction can adjust
+ the ssp by [0..255] value only thus use a loop if
+ the number of frames is bigger than 255. */
+ negq %rax
+ shrq $3, %rax
+ /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
+ restoring Shadow-Stack-Pointer of setjmp's caller, we
+ need to unwind shadow stack by one more frame. */
+ addq $1, %rax
+ cmpq $255, %rax
+ jbe .Lonetime
+.Loopadj:
+ incsspq %rax
+ subq $255, %rax
+ cmpq $255, %rax
+ ja .Loopadj
+.Lonetime:
+ incsspq %rax
+.Lnoadj:
+#endif
LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
/* We add unwind information for the target here. */
cfi_def_cfa(%rdi, 0)
new file mode 100644
@@ -0,0 +1,105 @@
+/* longjmp for Linux/x86-64 with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+/* Jump to the position specified by ENV, causing the
+ setjmp call there to return VAL, or 1 if VAL is 0.
+ void __longjmp (__jmp_buf env, int val). */
+ .text
+ENTRY(__longjmp)
+ /* Restore registers. */
+ mov (JB_RSP*8)(%rdi),%R8_LP
+ mov (JB_RBP*8)(%rdi),%R9_LP
+ mov (JB_PC*8)(%rdi),%RDX_LP
+#ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (%R8_LP)
+ PTR_DEMANGLE (%R9_LP)
+ PTR_DEMANGLE (%RDX_LP)
+# ifdef __ILP32__
+ /* We ignored the high bits of the %rbp value because only the low
+ bits are mangled. But we cannot presume that %rbp is being used
+ as a pointer and truncate it, so recover the high bits. */
+ movl (JB_RBP*8 + 4)(%rdi), %eax
+ shlq $32, %rax
+ orq %rax, %r9
+# endif
+#endif
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lnoadj
+# endif
+ /* Check and adjust the Shadow-Stack-Pointer. */
+ xorl %eax, %eax
+ /* Get the current ssp. */
+ rdsspq %rax
+ /* And compare it with the saved ssp value. */
+ subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax
+ je .Lnoadj
+ /* Count the number of frames to adjust and adjust it
+ with incssp instruction. The instruction can adjust
+ the ssp by [0..255] value only thus use a loop if
+ the number of frames is bigger than 255. */
+ negq %rax
+ shrq $3, %rax
+ /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
+ restoring Shadow-Stack-Pointer of setjmp's caller, we
+ need to unwind shadow stack by one more frame. */
+ addq $1, %rax
+ cmpq $255, %rax
+ jbe .Lonetime
+.Loopadj:
+ incsspq %rax
+ subq $255, %rax
+ cmpq $255, %rax
+ ja .Loopadj
+.Lonetime:
+ incsspq %rax
+.Lnoadj:
+#endif
+ LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP)
+ /* We add unwind information for the target here. */
+ cfi_def_cfa(%rdi, 0)
+ cfi_register(%rsp,%r8)
+ cfi_register(%rbp,%r9)
+ cfi_register(%rip,%rdx)
+ cfi_offset(%rbx,JB_RBX*8)
+ cfi_offset(%r12,JB_R12*8)
+ cfi_offset(%r13,JB_R13*8)
+ cfi_offset(%r14,JB_R14*8)
+ cfi_offset(%r15,JB_R15*8)
+ movq (JB_RBX*8)(%rdi),%rbx
+ movq (JB_R12*8)(%rdi),%r12
+ movq (JB_R13*8)(%rdi),%r13
+ movq (JB_R14*8)(%rdi),%r14
+ movq (JB_R15*8)(%rdi),%r15
+ /* Set return value for setjmp. */
+ mov %esi, %eax
+ mov %R8_LP,%RSP_LP
+ movq %r9,%rbp
+ LIBC_PROBE (longjmp_target, 3,
+ LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP)
+ jmpq *%rdx
+END (__longjmp)
new file mode 100644
@@ -0,0 +1,82 @@
+/* setjmp for Linux/x86-64 with shadow stack support.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <jmp_buf-ssp.h>
+#include <asm-syntax.h>
+#include <stap-probe.h>
+#include <jmp_buf-ssp.h>
+
+ENTRY (__sigsetjmp)
+ /* Save registers. */
+ movq %rbx, (JB_RBX*8)(%rdi)
+#ifdef PTR_MANGLE
+# ifdef __ILP32__
+ /* Save the high bits of %rbp first, since PTR_MANGLE will
+ only handle the low bits but we cannot presume %rbp is
+ being used as a pointer and truncate it. Here we write all
+ of %rbp, but the low bits will be overwritten below. */
+ movq %rbp, (JB_RBP*8)(%rdi)
+# endif
+ mov %RBP_LP, %RAX_LP
+ PTR_MANGLE (%RAX_LP)
+ mov %RAX_LP, (JB_RBP*8)(%rdi)
+#else
+ movq %rbp, (JB_RBP*8)(%rdi)
+#endif
+ movq %r12, (JB_R12*8)(%rdi)
+ movq %r13, (JB_R13*8)(%rdi)
+ movq %r14, (JB_R14*8)(%rdi)
+ movq %r15, (JB_R15*8)(%rdi)
+ lea 8(%rsp), %RDX_LP /* Save SP as it will be after we return. */
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%RDX_LP)
+#endif
+ movq %rdx, (JB_RSP*8)(%rdi)
+ mov (%rsp), %RAX_LP /* Save PC we are returning to now. */
+ LIBC_PROBE (setjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RAX_LP)
+#ifdef PTR_MANGLE
+ PTR_MANGLE (%RAX_LP)
+#endif
+ movq %rax, (JB_PC*8)(%rdi)
+
+#ifdef __SHSTK__
+# if IS_IN (libc) && defined SHARED
+ /* Check if Shadow Stack is enabled. */
+ testl $(1 << 1), %fs:FEATURE_1_OFFSET
+ jz .Lskip_ssp
+# endif
+ /* Get the current Shadow-Stack-Pointer and save it. */
+ xorl %eax, %eax
+ rdsspq %rax
+ movq %rax, SHADOW_STACK_POINTER_OFFSET(%rdi)
+# if IS_IN (libc) && defined SHARED
+.Lskip_ssp:
+# endif
+#endif
+#if IS_IN (rtld)
+ /* In ld.so we never save the signal mask. */
+ xorl %eax, %eax
+ retq
+#else
+ /* Make a tail call to __sigjmp_save; it takes the same args. */
+ jmp __sigjmp_save
+#endif
+END (__sigsetjmp)
+hidden_def (__sigsetjmp)