about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-07-30 17:31:48 -0700
committerUlrich Drepper <drepper@redhat.com>2009-07-30 17:31:48 -0700
commit5ead9ce5c788e7dbb0bd01888c4bcb37a8bc2ff1 (patch)
treefaf3f4efb3881c34c4eeb54a60f4b1f0e1570ef5
parent2dec6007d183aa51abedbbb048382973129f3935 (diff)
downloadglibc-5ead9ce5c788e7dbb0bd01888c4bcb37a8bc2ff1.tar.gz
glibc-5ead9ce5c788e7dbb0bd01888c4bcb37a8bc2ff1.tar.xz
glibc-5ead9ce5c788e7dbb0bd01888c4bcb37a8bc2ff1.zip
Fix x86-64 ____longjmp_chk to handle signal stacks.
The simple test previously used might trigger if the longjmp jumps
from the signal stack to the normal stack.  We now explicitly test
for this case.
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/x86_64/____longjmp_chk.S107
-rw-r--r--sysdeps/x86_64/__longjmp.S6
3 files changed, 111 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 9e78199bce..2492d49314 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2009-07-30  Ulrich Drepper  <drepper@redhat.com>
 
+	* sysdeps/x86_64/__longjmp.S: Remove CHECK_RSP handling.  Fix CFI.
+	Remove incorrect use of BP_SYM.
+	* sysdeps/x86_64/____longjmp_chk.S: Rewrite.  Complete implementation
+	here now since it is more complex than just a simple check.
+
 	* sysdeps/ia64/backtrace.c (backtrace_helper): Stop backtrace when
 	we make no more progress.
 
diff --git a/sysdeps/x86_64/____longjmp_chk.S b/sysdeps/x86_64/____longjmp_chk.S
index 030a0dcaa7..50d2fca2c3 100644
--- a/sysdeps/x86_64/____longjmp_chk.S
+++ b/sysdeps/x86_64/____longjmp_chk.S
@@ -16,6 +16,10 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <sysdep.h>
+#include <jmpbuf-offsets.h>
+#include <asm-syntax.h>
+
 	.section .rodata.str1.1,"aMS",@progbits,1
 	.type	longjmp_msg,@object
 longjmp_msg:
@@ -23,7 +27,7 @@ longjmp_msg:
 	.size	longjmp_msg, .-longjmp_msg
 
 
-#define __longjmp ____longjmp_chk
+//#define __longjmp ____longjmp_chk
 
 #ifdef PIC
 # define CALL_FAIL	leaq	longjmp_msg(%rip), %rdi;		      \
@@ -39,4 +43,103 @@ longjmp_msg:
 	CALL_FAIL;							      \
 .Lok:
 
-#include "__longjmp.S"
+/* 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_chk)
+	/* Restore registers.  */
+	movq	(JB_RSP*8)(%rdi),%r8
+	movq	(JB_RBP*8)(%rdi),%r9
+	movq	(JB_PC*8)(%rdi),%rdx
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (%r8)
+	PTR_DEMANGLE (%r9)
+	PTR_DEMANGLE (%rdx)
+#endif
+
+	/* Save function parameters.  */
+	movq	%rdi, %r10
+	movl	%esi, %ecx
+
+	xorl	%eax, %eax
+	cmpq	%r8, %rsp
+	jbe	.Lok
+
+	subq	$32, %rsp
+	cfi_adjust_cfa_offset(32)
+	movq	%r10, 24(%rsp)
+	xorl	%edi, %edi
+	movq	%rsp, %rsi
+	movl	$__NR_sigaltstack, %eax
+	syscall
+	movq	24(%rsp), %r10
+	testl	%eax, %eax
+	movl	$0, %eax
+	jne	.Lok
+	movl	8(%rsp), %eax
+	andl	$1, %eax
+
+.Lok:
+	/* We add unwind information for the target here.  */
+	cfi_def_cfa(%r10, 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)
+
+	xchgq	%r8, %rsp
+	cfi_restore(%rsp)
+	xchgq	%r9, %rbp
+	cfi_restore(%rbp)
+
+	movq	(JB_RBX*8)(%r10),%rbx
+	movq	(JB_R12*8)(%r10),%r12
+	movq	(JB_R13*8)(%r10),%r13
+	movq	(JB_R14*8)(%r10),%r14
+	movq	(JB_R15*8)(%r10),%r15
+
+	cmpq	%rsp, %r8
+	jnbe	.Lcheck
+
+	/* Set return value for setjmp.  */
+.Lout:	movl	%ecx, %eax
+	jmpq	*%rdx
+
+.Lcheck:
+	testl	%eax, %eax
+	je	.Lfail
+
+	subq	$24, %rsp
+	cfi_adjust_cfa_offset(24)
+	xorl	%edi, %edi
+	movq	%rsp, %rsi
+	movl	$__NR_sigaltstack, %eax
+	syscall
+	addq	$24, %rsp
+	cfi_adjust_cfa_offset(-24)
+	testl	$1, 8(%rsp)
+	je	.Lout
+
+.Lfail:	xchgq	%r8, %rsp
+	/* We want the stack trace to show that of the caller.  */
+	cfi_def_cfa(%rsp, 40)
+	cfi_restore(%rsp)
+	cfi_register(%rbp, %r9)
+	cfi_restore(%rip)
+	cfi_restore(%rbx)
+	cfi_restore(%r12)
+	cfi_restore(%r13)
+	cfi_restore(%r14)
+	cfi_restore(%r15)
+
+	xchgq	%r9, %rbp
+	cfi_restore(%rbp)
+
+	CALL_FAIL
+	hlt
+END (BP_SYM (____longjmp_chk))
diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
index 24552ece37..b045c04184 100644
--- a/sysdeps/x86_64/__longjmp.S
+++ b/sysdeps/x86_64/__longjmp.S
@@ -34,16 +34,12 @@ ENTRY(__longjmp)
 	PTR_DEMANGLE (%r9)
 	PTR_DEMANGLE (%rdx)
 #endif
-#ifdef CHECK_RSP
-	CHECK_RSP (%r8)
-#endif
 	/* 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(%rbp,JB_RBP*8)
 	cfi_offset(%r12,JB_R12*8)
 	cfi_offset(%r13,JB_R13*8)
 	cfi_offset(%r14,JB_R14*8)
@@ -58,4 +54,4 @@ ENTRY(__longjmp)
 	movq %r8,%rsp
 	movq %r9,%rbp
 	jmpq *%rdx
-END (BP_SYM (__longjmp))
+END (__longjmp)