OSDN Git Service

Hacked things so longjmp now works.
authorEric Andersen <andersen@codepoet.org>
Thu, 6 Jul 2000 06:37:55 +0000 (06:37 -0000)
committerEric Andersen <andersen@codepoet.org>
Thu, 6 Jul 2000 06:37:55 +0000 (06:37 -0000)
 -Erik

include/setjmp.h
libc/sysdeps/linux/i386/bits/setjmp.h
libc/sysdeps/linux/i386/bits/sigset.h [new file with mode: 0644]
libc/sysdeps/linux/i386/setjmp.S

index 53d0223..821e20b 100644 (file)
@@ -1,22 +1,99 @@
+/* Copyright (C) 1991,92,93,94,95,96,97,98 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
 /*
-       setjmp.h
-       stubs for future use.
-*/
+ *     ISO C Standard: 4.6 NON-LOCAL JUMPS     <setjmp.h>
+ */
 
-#ifndef _SETJMP_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-#define _SETJMP_H_
+#ifndef        _SETJMP_H
+#define        _SETJMP_H       1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+#include <machine/setjmp.h>            /* Get `__jmp_buf'.  */
+#include <machine/sigset.h>            /* Get `__sigset_t'.  */
+
+/* Calling environment, plus possibly a saved signal mask.  */
+typedef struct __jmp_buf_tag   /* C++ doesn't like tagless structs.  */
+  {
+    /* NOTE: The machine-dependent definitions of `__sigsetjmp'
+       assume that a `jmp_buf' begins with a `__jmp_buf'.
+       Do not move this member or add others before it.  */
+    __jmp_buf __jmpbuf;                /* Calling environment.  */
+    int __mask_was_saved;      /* Saved the signal mask?  */
+    __sigset_t __saved_mask;   /* Saved signal mask.  */
+  } jmp_buf[1];
 
-#include "_ansi.h"
-#include <machine/setjmp.h>
 
-void   _EXFUN(longjmp,(jmp_buf __jmpb, int __retval));
-int    _EXFUN(setjmp,(jmp_buf __jmpb));
+/* Store the calling environment in ENV, also saving the
+   signal mask if SAVEMASK is nonzero.  Return 0.
+   This is the internal name for `sigsetjmp'.  */
+extern int __sigsetjmp __P ((jmp_buf __env, int __savemask));
 
-#ifdef __cplusplus
-}
+#ifndef        __FAVOR_BSD
+/* Set ENV to the current position and return 0, not saving the signal mask.
+   This is just like `sigsetjmp (ENV, 0)'.
+   The ISO C standard says `setjmp' is a macro.  */
+# define setjmp(env)   __sigsetjmp ((env), 0)
+#else
+/* We are in 4.3 BSD-compatibility mode in which `setjmp'
+   saves the signal mask like `sigsetjmp (ENV, 1)'.  */
+# define setjmp(env)   __sigsetjmp ((env), 1)
+#endif /* Favor BSD.  */
+
+#if defined __USE_BSD || defined __USE_XOPEN
+/* Set ENV to the current position and return 0, not saving the signal mask.
+   This is the 4.3 BSD name for ISO `setjmp'.  */
+# define _setjmp(env)  __sigsetjmp ((env), 0)
 #endif
-#endif /* _SETJMP_H_ */
 
+
+/* Jump to the environment saved in ENV, making the
+   `setjmp' call there return VAL, or 1 if VAL is 0.  */
+extern void longjmp __P ((jmp_buf __env, int __val))
+     __attribute__ ((__noreturn__));
+#if defined __USE_BSD || defined __USE_XOPEN
+/* Same.  Usually `_longjmp' is used with `_setjmp', which does not save
+   the signal mask.  But it is how ENV was saved that determines whether
+   `longjmp' restores the mask; `_longjmp' is just an alias.  */
+extern void _longjmp __P ((jmp_buf __env, int __val))
+     __attribute__ ((__noreturn__));
+#endif
+
+
+/* Use the same type for `jmp_buf' and `sigjmp_buf'.
+   The `__mask_was_saved' flag determines whether
+   or not `longjmp' will restore the signal mask.  */
+typedef jmp_buf sigjmp_buf;
+
+/* Store the calling environment in ENV, also saving the
+   signal mask if SAVEMASK is nonzero.  Return 0.  */
+# define sigsetjmp(env, savemask)      __sigsetjmp ((env), (savemask))
+
+/* Jump to the environment saved in ENV, making the
+   sigsetjmp call there return VAL, or 1 if VAL is 0.
+   Restore the signal mask if that sigsetjmp call saved it.
+   This is just an alias `longjmp'.  */
+extern void siglongjmp __P ((sigjmp_buf __env, int __val))
+     __attribute__ ((__noreturn__));
+
+__END_DECLS
+
+#endif /* setjmp.h  */
index 20786d6..2f5b445 100644 (file)
-#if defined(__arm__) || defined(__thumb__)
-/*
- * All callee preserved registers:
- * v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7
- */
-#define _JBLEN 23
-#endif
-
-#ifdef __sparc__
-/*
- * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext).
- * All else recovered by under/over(flow) handling.
- */
-#define        _JBLEN  13
-#endif
-
-/* necv70 was 9 as well. */
-
-#ifdef __mc68000__
-/*
- * onsstack,sigmask,sp,pc,psl,d2-d7,a2-a6,
- * fp2-fp7     for 68881.
- * All else recovered by under/over(flow) handling.
- */
-#define        _JBLEN  34
-#endif
-
-#if defined(__Z8001__) || defined(__Z8002__)
-/* 16 regs + pc */
-#define _JBLEN 20
-#endif
-
-#ifdef _AM29K
-/*
- * onsstack,sigmask,sp,pc,npc,psr,g1,o0,wbcnt (sigcontext).
- * All else recovered by under/over(flow) handling.
- */
-#define        _JBLEN  9
-#endif
-
-#ifdef __i386__
-#ifdef __unix__
-# define _JBLEN        36
-#elif defined(_WIN32)
-#define _JBLEN (13 * 4)
-#else
-#include "setjmp-dj.h"
-#endif
-#endif
-
-#ifdef __i960__
-#define _JBLEN 35
-#endif
-
-#ifdef __M32R__
-/* Only 8 words are currently needed.  10 gives us some slop if we need
-   to expand.  */
-#define _JBLEN 10
-#endif
-
-#ifdef __mips__
-#define _JBLEN 11
-#endif
-
-#ifdef __m88000__
-#define _JBLEN 21
-#endif
-
-#ifdef __H8300__
-#define _JBLEN 5
-typedef int jmp_buf[_JBLEN];
-#endif
-
-#ifdef __H8300H__
-/* same as H8/300 but registers are twice as big */
-#define _JBLEN 5
-#define _JBTYPE long
-#endif
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-#ifdef __H8300S__
-/* same as H8/300 but registers are twice as big */
-#define _JBLEN 5
-#define _JBTYPE long
-#endif
-
-#ifdef __H8500__
-#define _JBLEN 4
-#endif
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-#ifdef  __sh__
-#define _JBLEN 20
-#endif
+   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
+   Library General Public License for more details.
 
-#ifdef  __v800
-#define _JBLEN 28
-#endif
-
-#ifdef __PPC__
-#define _JBLEN 32
-#define _JBTYPE double
-#endif
-
-#ifdef __hppa__
-/* %r30, %r2-%r18, %r27, pad, %fr12-%fr15.
-   Note space exists for the FP registers, but they are not
-   saved.  */
-#define _JBLEN 28
-#endif
-
-#if defined(mn10300) || defined(mn10200)
-/* A guess */
-#define _JBLEN 10
-#endif
-
-#ifdef __v850
-/* I think our setjmp is saving 15 regs at the moment.  Gives us one word
-   slop if we need to expand.  */
-#define _JBLEN 16
-#endif
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
+/* Define the machine-dependent type `jmp_buf'.  Intel 386 version.  */
 
-#ifdef __D10V__
-#define _JBLEN 8
+#ifndef _SETJMP_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
 #endif
 
-/* start-sanitize-d30v */
-#ifdef __D30V__
-#define _JBLEN (64 /* GPR */ + (2*2) /* ACs */ + 18 /* CRs */)
+#if defined __USE_MISC || defined _ASM
+# define JB_BX 0
+# define JB_SI 1
+# define JB_DI 2
+# define JB_BP 3
+# define JB_SP 4
+# define JB_PC 5
 #endif
-/* end-sanitize-d30v */
 
-#ifdef _JBLEN
-#ifdef _JBTYPE
-typedef        _JBTYPE jmp_buf[_JBLEN];
-#else
-typedef        int jmp_buf[_JBLEN];
+#ifndef        _ASM
+typedef int __jmp_buf[6];
 #endif
 
-#ifdef __CYGWIN32__
-#include <signal.h>
-
-/* POSIX sigsetjmp/siglongjmp macros */
-typedef int sigjmp_buf[_JBLEN+2];
-
-#define _SAVEMASK      _JBLEN
-#define _SIGMASK       (_JBLEN+1)
-
-#define sigsetjmp(env, savemask) (env[_SAVEMASK] = savemask,\
-               sigprocmask (SIG_SETMASK, 0, (sigset_t *) &env[_SIGMASK]),\
-               setjmp (env))
-
-#define siglongjmp(env, val) (((env[_SAVEMASK])?\
-               sigprocmask (SIG_SETMASK, (sigset_t *) &env[_SIGMASK], 0):0),\
-               longjmp (env, val))
-
-#endif /* __CYGWIN32__*/
-
-#if defined(__linux__) && defined(__mc68000__)
-#include <signal.h>
-
-/* POSIX sigsetjmp/siglongjmp macros */
-typedef int sigjmp_buf[_JBLEN];
-
-#define _SAVEMASK      4
-#define _SIGMASK       1
-
-#define sigsetjmp(env, savemask) (env[_SAVEMASK] = savemask,\
-               sigprocmask (SIG_SETMASK, 0, (sigset_t *) &env[_SIGMASK]),\
-               setjmp (env))
-
-#define siglongjmp(env, val) (((env[_SAVEMASK])?\
-               sigprocmask (SIG_SETMASK, (sigset_t *) &env[_SIGMASK], 0):0),\
-               longjmp (env, val))
-
-#endif /* __linux__*/
-#endif
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address) \
+  ((void *) (address) < (void *) (jmpbuf)[JB_SP])
diff --git a/libc/sysdeps/linux/i386/bits/sigset.h b/libc/sysdeps/linux/i386/bits/sigset.h
new file mode 100644 (file)
index 0000000..66a9c51
--- /dev/null
@@ -0,0 +1,125 @@
+/* __sig_atomic_t, __sigset_t, and related definitions.  Linux version.
+   Copyright (C) 1991, 1992, 1994, 1996, 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef        _SIGSET_H_types
+# define _SIGSET_H_types       1
+
+typedef int __sig_atomic_t;
+
+/* A `sigset_t' has a bit for each signal.  */
+
+# define _SIGSET_NWORDS        (1024 / (8 * sizeof (unsigned long int)))
+typedef struct
+  {
+    unsigned long int __val[_SIGSET_NWORDS];
+  } __sigset_t;
+
+#endif
+
+
+/* We only want to define these functions if <signal.h> was actually
+   included; otherwise we were included just to define the types.  Since we
+   are namespace-clean, it wouldn't hurt to define extra macros.  But
+   trouble can be caused by functions being defined (e.g., any global
+   register vars declared later will cause compilation errors).  */
+
+#if !defined _SIGSET_H_fns && defined _SIGNAL_H
+# define _SIGSET_H_fns 1
+
+# ifndef _EXTERN_INLINE
+#  define _EXTERN_INLINE extern __inline
+# endif
+
+/* Return a mask that includes the bit for SIG only.  */
+# define __sigmask(sig) \
+  (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int))))
+
+/* Return the word index for SIG.  */
+# define __sigword(sig)        (((sig) - 1) / (8 * sizeof (unsigned long int)))
+
+# if defined __GNUC__ && __GNUC__ >= 2
+#  define __sigemptyset(set) \
+  (__extension__ ({ int __cnt = _SIGSET_NWORDS;                                      \
+                   sigset_t *__set = (set);                                  \
+                   while (--__cnt >= 0) __set->__val[__cnt] = 0;             \
+                   0; }))
+#  define __sigfillset(set) \
+  (__extension__ ({ int __cnt = _SIGSET_NWORDS;                                      \
+                   sigset_t *__set = (set);                                  \
+                   while (--__cnt >= 0) __set->__val[__cnt] = ~0UL;          \
+                   0; }))
+
+#  ifdef __USE_GNU
+/* The POSIX does not specify for handling the whole signal set in one
+   command.  This is often wanted and so we define three more functions
+   here.  */
+#   define __sigisemptyset(set) \
+  (__extension__ ({ int __cnt = _SIGSET_NWORDS;                                      \
+                   const sigset_t *__set = (set);                            \
+                   int __ret = __set->__val[--__cnt];                        \
+                   while (!__ret && --__cnt >= 0)                            \
+                       __ret = __set->__val[__cnt];                          \
+                   __ret == 0; }))
+#   define __sigandset(dest, left, right) \
+  (__extension__ ({ int __cnt = _SIGSET_NWORDS;                                      \
+                   sigset_t *__dest = (dest);                                \
+                   const sigset_t *__left = (left);                          \
+                   const sigset_t *__right = (right);                        \
+                   while (--__cnt >= 0)                                      \
+                     __dest->__val[__cnt] = (__left->__val[__cnt]            \
+                                             & __right->__val[__cnt]);       \
+                   0; }))
+#   define __sigorset(dest, left, right) \
+  (__extension__ ({ int __cnt = _SIGSET_NWORDS;                                      \
+                   sigset_t *__dest = (dest);                                \
+                   const sigset_t *__left = (left);                          \
+                   const sigset_t *__right = (right);                        \
+                   while (--__cnt >= 0)                                      \
+                     __dest->__val[__cnt] = (__left->__val[__cnt]            \
+                                             | __right->__val[__cnt]);       \
+                   0; }))
+#  endif
+# endif
+
+/* These functions needn't check for a bogus signal number -- error
+   checking is done in the non __ versions.  */
+
+extern int __sigismember (__const __sigset_t *, int);
+extern int __sigaddset (__sigset_t *, int);
+extern int __sigdelset (__sigset_t *, int);
+
+# ifdef __USE_EXTERN_INLINES
+#  define __SIGSETFN(NAME, BODY, CONST)                                              \
+  _EXTERN_INLINE int                                                         \
+  NAME (CONST __sigset_t *__set, int __sig)                                  \
+  {                                                                          \
+    unsigned long int __mask = __sigmask (__sig);                            \
+    unsigned long int __word = __sigword (__sig);                            \
+    return BODY;                                                             \
+  }
+
+__SIGSETFN (__sigismember, (__set->__val[__word] & __mask) ? 1 : 0, __const)
+__SIGSETFN (__sigaddset, ((__set->__val[__word] |= __mask), 0), )
+__SIGSETFN (__sigdelset, ((__set->__val[__word] &= ~__mask), 0), )
+
+#  undef __SIGSETFN
+# endif
+
+
+#endif /* ! _SIGSET_H_fns.  */
index 3ff0542..d6f2cba 100644 (file)
@@ -1,88 +1,59 @@
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-.global SYM (setjmp)
-.global SYM (longjmp)
-
-SYM (setjmp):
-       moveal sp@(4),a0
-       movel sp@(0),a0@(12)
-       movel sp,a0@(8)
-       moveml d2-d7/a2-a6,a0@(20)
-       clrl d0
-       rts
-
-SYM (longjmp):
-       moveal sp@(4),a0
-       movel sp@(8),d0
-       bne 1f
-       movel #1,d0
-1:
-       moveml a0@(20),d2-d7/a2-a6
-       moveal a0@(8),sp
-       movel a0@(12),sp@
-       rts
-
-#ifdef M68881
-.global SYM (setjmp_68881)
-.global SYM (longjmp_68881)
-
-SYM (setjmp_68881):
-       moveal sp@(4),a0
-       movel sp@(0),a0@(12)
-       movel sp,a0@(8)
-       moveml d2-d7/a2-a6,a0@(20)
-       fmovemx fp2-fp7,a0@(64)
-       clrl d0
-       rts
-
-SYM (longjmp_68881):
-       moveal sp@(4),a0
-       fmovemx a0@(64),fp2-fp7
-       movel sp@(8),d0
-       bne 1f
-       movel #1,d0
-1:
-       moveml a0@(20),d2-d7/a2-a6
-       moveal a0@(8),sp
-       movel a0@(12),sp@
-       rts
+/* setjmp for i386.
+   Copyright (C) 1995, 1996, 1997 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <sysdep.h>
+#define _ASM
+#define _SETJMP_H
+#include <machine/setjmp.h>
+
+ENTRY (__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.  */
+
+ENTRY (__sigsetjmp)
+       movl 4(%esp), %eax      /* User's jmp_buf in %eax.  */
+       /* Save registers.  */
+       movl %ebx, (JB_BX*4)(%eax)
+       movl %esi, (JB_SI*4)(%eax)
+       movl %edi, (JB_DI*4)(%eax)
+       movl %ebp, (JB_BP*4)(%eax)
+       leal 4(%esp), %ecx      /* Save SP as it will be after we return.  */
+       movl %ecx, (JB_SP*4)(%eax)
+       movl 0(%esp), %ecx      /* Save PC we are returning to now.  */
+       movl %ecx, (JB_PC*4)(%eax)
+
+       /* Make a tail call to __sigjmp_save; it takes the same args.  */
+#ifdef PIC
+       /* We cannot use the PLT, because it requires that %ebx be set, but
+           we can't save and restore our caller's value.  Instead, we do an
+           indirect jump through the GOT, using for the temporary register
+           %ecx, which is call-clobbered.  */
+       call L(here)
+L(here):
+       popl %ecx
+       addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ecx
+       movl C_SYMBOL_NAME(__sigjmp_save@GOT)(%ecx), %ecx
+       jmp *%ecx
+#else
+       jmp __sigjmp_save
 #endif
+.size __sigsetjmp,.-__sigsetjmp;