Back to index

glibc  2.9
sigaction.c
Go to the documentation of this file.
00001 /* POSIX.1 `sigaction' call for Linux/x86-64.
00002    Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <sysdep.h>
00021 #include <errno.h>
00022 #include <stddef.h>
00023 #include <signal.h>
00024 #include <string.h>
00025 
00026 #include <sysdep.h>
00027 #include <sys/syscall.h>
00028 
00029 #include <kernel-features.h>
00030 
00031 /* The difference here is that the sigaction structure used in the
00032    kernel is not the same as we use in the libc.  Therefore we must
00033    translate it here.  */
00034 #include <kernel_sigaction.h>
00035 
00036 #include "ucontext_i.h"
00037 
00038 /* We do not globally define the SA_RESTORER flag so do it here.  */
00039 #define SA_RESTORER 0x04000000
00040 
00041 /* Using the hidden attribute here does not change the code but it
00042    helps to avoid warnings.  */
00043 extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
00044 
00045 
00046 /* If ACT is not NULL, change the action for SIG to *ACT.
00047    If OACT is not NULL, put the old action for SIG in *OACT.  */
00048 int
00049 __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
00050 {
00051   int result;
00052   struct kernel_sigaction kact, koact;
00053 
00054   if (act)
00055     {
00056       kact.k_sa_handler = act->sa_handler;
00057       memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
00058       kact.sa_flags = act->sa_flags | SA_RESTORER;
00059 
00060       kact.sa_restorer = &restore_rt;
00061     }
00062 
00063   /* XXX The size argument hopefully will have to be changed to the
00064      real size of the user-level sigset_t.  */
00065   result = INLINE_SYSCALL (rt_sigaction, 4,
00066                         sig, act ? __ptrvalue (&kact) : NULL,
00067                         oact ? __ptrvalue (&koact) : NULL, _NSIG / 8);
00068   if (oact && result >= 0)
00069     {
00070       oact->sa_handler = koact.k_sa_handler;
00071       memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
00072       oact->sa_flags = koact.sa_flags;
00073       oact->sa_restorer = koact.sa_restorer;
00074     }
00075   return result;
00076 }
00077 libc_hidden_def (__libc_sigaction)
00078 
00079 #ifdef WRAPPER_INCLUDE
00080 # include WRAPPER_INCLUDE
00081 #endif
00082 
00083 #ifndef LIBC_SIGACTION
00084 weak_alias (__libc_sigaction, __sigaction)
00085 libc_hidden_weak (__sigaction)
00086 weak_alias (__libc_sigaction, sigaction)
00087 #endif
00088 
00089 /* NOTE: Please think twice before making any changes to the bits of
00090    code below.  GDB needs some intimate knowledge about it to
00091    recognize them as signal trampolines, and make backtraces through
00092    signal handlers work right.  Important are both the names
00093    (__restore_rt) and the exact instruction sequence.
00094    If you ever feel the need to make any changes, please notify the
00095    appropriate GDB maintainer.
00096 
00097    The unwind information starts a byte before __restore_rt, so that
00098    it is found when unwinding, to get an address the unwinder assumes
00099    will be in the middle of a call instruction.  See the Linux kernel
00100    (the i386 vsyscall, in particular) for an explanation of the complex
00101    unwind information used here in order to get the traditional CFA.
00102    We do not restore cs - it's only stored as two bytes here so that's
00103    a bit tricky.  We don't use the gas cfi directives, so that we can
00104    reliably add .cfi_signal_frame.  */
00105 
00106 #define do_cfa_expr                                     \
00107   "    .byte 0x0f\n"        /* DW_CFA_def_cfa_expression */    \
00108   "    .uleb128 2f-1f\n"    /* length */                \
00109   "1:  .byte 0x77\n"        /* DW_OP_breg7 */           \
00110   "    .sleb128 " CFI_STRINGIFY (oRSP) "\n"                    \
00111   "    .byte 0x06\n"        /* DW_OP_deref */           \
00112   "2:"
00113 
00114 #define do_expr(regno, offset)                                 \
00115   "    .byte 0x10\n"        /* DW_CFA_expression */            \
00116   "    .uleb128 " CFI_STRINGIFY (regno) "\n"                   \
00117   "    .uleb128 2f-1f\n"    /* length */                \
00118   "1:  .byte 0x77\n"        /* DW_OP_breg7 */           \
00119   "    .sleb128 " CFI_STRINGIFY (offset) "\n"                  \
00120   "2:"
00121 
00122 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
00123 # define RESTORE2(name, syscall) \
00124 asm                                                            \
00125   (                                                            \
00126    /* `nop' for debuggers assuming `call' should not disalign the code.  */ \
00127    "   nop\n"                                                  \
00128    ".align 16\n"                                               \
00129    ".LSTART_" #name ":\n"                                      \
00130    "   .type __" #name ",@function\n"                                 \
00131    "__" #name ":\n"                                            \
00132    "   movq $" #syscall ", %rax\n"                             \
00133    "   syscall\n"                                              \
00134    ".LEND_" #name ":\n"                                               \
00135    ".section .eh_frame,\"a\",@progbits\n"                      \
00136    ".LSTARTFRAME_" #name ":\n"                                        \
00137    "   .long .LENDCIE_" #name "-.LSTARTCIE_" #name "\n"        \
00138    ".LSTARTCIE_" #name ":\n"                                          \
00139    "   .long 0\n"    /* CIE ID */                              \
00140    "   .byte 1\n"    /* Version number */                      \
00141    "   .string \"zRS\"\n" /* NUL-terminated augmentation string */    \
00142    "   .uleb128 1\n" /* Code alignment factor */               \
00143    "   .sleb128 -8\n"       /* Data alignment factor */               \
00144    "   .uleb128 16\n"       /* Return address register column (rip) */       \
00145    /* Augmentation value length */                             \
00146    "   .uleb128 .LENDAUGMNT_" #name "-.LSTARTAUGMNT_" #name "\n"      \
00147    ".LSTARTAUGMNT_" #name ":\n"                                       \
00148    "   .byte 0x1b\n" /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */            \
00149    ".LENDAUGMNT_" #name ":\n"                                         \
00150    "   .align 8\n"                                             \
00151    ".LENDCIE_" #name ":\n"                                     \
00152    "   .long .LENDFDE_" #name "-.LSTARTFDE_" #name "\n" /* FDE len */ \
00153    ".LSTARTFDE_" #name ":\n"                                          \
00154    "   .long .LSTARTFDE_" #name "-.LSTARTFRAME_" #name "\n" /* CIE */ \
00155    /* `LSTART_' is subtracted 1 as debuggers assume a `call' here.  */       \
00156    "   .long (.LSTART_" #name "-1)-.\n" /* PC-relative start addr.  */       \
00157    "   .long .LEND_" #name "-(.LSTART_" #name "-1)\n"                 \
00158    "   .uleb128 0\n"               /* FDE augmentation length */      \
00159    do_cfa_expr                                                        \
00160    do_expr (8 /* r8 */, oR8)                                          \
00161    do_expr (9 /* r9 */, oR9)                                          \
00162    do_expr (10 /* r10 */, oR10)                                       \
00163    do_expr (11 /* r11 */, oR11)                                       \
00164    do_expr (12 /* r12 */, oR12)                                       \
00165    do_expr (13 /* r13 */, oR13)                                       \
00166    do_expr (14 /* r14 */, oR14)                                       \
00167    do_expr (15 /* r15 */, oR15)                                       \
00168    do_expr (5 /* rdi */, oRDI)                                        \
00169    do_expr (4 /* rsi */, oRSI)                                        \
00170    do_expr (6 /* rbp */, oRBP)                                        \
00171    do_expr (3 /* rbx */, oRBX)                                        \
00172    do_expr (1 /* rdx */, oRDX)                                        \
00173    do_expr (0 /* rax */, oRAX)                                        \
00174    do_expr (2 /* rcx */, oRCX)                                        \
00175    do_expr (7 /* rsp */, oRSP)                                        \
00176    do_expr (16 /* rip */, oRIP)                                       \
00177    /* libgcc-4.1.1 has only `DWARF_FRAME_REGISTERS == 17'.  */        \
00178    /* do_expr (49 |* rflags *|, oEFL) */                       \
00179    /* `cs'/`ds'/`fs' are unaligned and a different size.  */          \
00180    /* gas: Error: register save offset not a multiple of 8  */        \
00181    "   .align 8\n"                                             \
00182    ".LENDFDE_" #name ":\n"                                     \
00183    "   .previous\n"                                            \
00184    );
00185 /* The return code for realtime-signals.  */
00186 RESTORE (restore_rt, __NR_rt_sigreturn)