From 8a309c2fde98f9fcba538fcada54248eafdd34ad Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Fri, 5 Oct 2001 11:31:48 +0000 Subject: Wohoo! David McCullough found the bug! His comments follow: I had a look at it and you won't believe it was always broken. I'll try and explain it, let me know if it doesn't make sense. * ash calls setjmp, which messes with the stack to look like it has two args instead of one and then jmps (actually falls) into sigsetjmp. BUG * sigsetjmp then saves the registers and "jumps" to __sigset_save, a C function. BUG1 - because the caller pops its args off the stack, a program that changes it's number of args is broken because the caller will not pop the correct number of args. I think that jumping from the sigsetjmp asm to the 'C' code is unsafe but I can't think of an example. Anyway, I have attached what I think is a working fix. The reason this worked without -fomit-frame-pointer is that the _sigset_save 'C' code would restore the stack pointer from %ebp (the frame pointer) and because none of the asm had moded it, when we returned from __sigset_save the stack was back to it's correct position for 1 argument despite our best attempts to stuff it up ;-) --- libc/sysdeps/linux/i386/setjmp.S | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'libc/sysdeps/linux') diff --git a/libc/sysdeps/linux/i386/setjmp.S b/libc/sysdeps/linux/i386/setjmp.S index 729414390..d38437b6b 100644 --- a/libc/sysdeps/linux/i386/setjmp.S +++ b/libc/sysdeps/linux/i386/setjmp.S @@ -21,16 +21,6 @@ #define _SETJMP_H #include -.globl _setjmp; -.type _setjmp,@function -.align 4; \ -_setjmp: - popl %eax /* Pop return address. */ - popl %ecx /* Pop jmp_buf. */ - pushl $0 /* Push zero argument. */ - pushl %ecx /* Push jmp_buf. */ - pushl %eax /* Push back return address. */ - .globl __sigsetjmp; .type __sigsetjmp,@function .align 4; \ @@ -46,6 +36,9 @@ __sigsetjmp: movl 0(%esp), %ecx /* Save PC we are returning to now. */ movl %ecx, (JB_PC*4)(%eax) + pushl 0x8(%esp) /* save mask */ + pushl 0x8(%esp) /* jump buf */ + /* Make a tail call to __sigjmp_save; it takes the same args. */ #if defined(PIC) /* We cannot use the PLT, because it requires that %ebx be set, but @@ -57,8 +50,23 @@ Lhere: popl %ecx addl $_GLOBAL_OFFSET_TABLE_+[.-Lhere], %ecx movl (__sigjmp_save)(%ecx), %ecx - jmp *%ecx + call *%ecx #else - jmp __sigjmp_save + call __sigjmp_save #endif + + add $8, %esp + ret .size __sigsetjmp,.-__sigsetjmp; + +.globl _setjmp; +.type _setjmp,@function +.align 4; \ +_setjmp: + pushl $0 /* Push zero argument. */ + pushl 0x8(%esp) /* Push jmp_buf. */ + call __sigsetjmp + add $8, %esp + ret +.size _setjmp,.-_setjmp; + -- cgit v1.2.3