Blame sysdeps/unix/sysv/linux/x86_64/sigaction.c

Packit 6c4009
/* POSIX.1 `sigaction' call for Linux/x86-64.
Packit 6c4009
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <signal.h>
Packit 6c4009
#define SA_RESTORER 0x04000000
Packit 6c4009
#include <kernel_sigaction.h>
Packit 6c4009
Packit 6c4009
extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
Packit 6c4009
Packit 6c4009
#define SET_SA_RESTORER(kact, act)			\
Packit 6c4009
  (kact)->sa_flags = (act)->sa_flags | SA_RESTORER;	\
Packit 6c4009
  (kact)->sa_restorer = &restore_rt
Packit 6c4009
Packit 6c4009
#define RESET_SA_RESTORER(act, kact) 			\
Packit 6c4009
  (act)->sa_restorer = (kact)->sa_restorer
Packit 6c4009
Packit 6c4009
#include <sysdeps/unix/sysv/linux/sigaction.c>
Packit 6c4009
Packit 6c4009
/* NOTE: Please think twice before making any changes to the bits of
Packit 6c4009
   code below.  GDB needs some intimate knowledge about it to
Packit 6c4009
   recognize them as signal trampolines, and make backtraces through
Packit 6c4009
   signal handlers work right.  Important are both the names
Packit 6c4009
   (__restore_rt) and the exact instruction sequence.
Packit 6c4009
   If you ever feel the need to make any changes, please notify the
Packit 6c4009
   appropriate GDB maintainer.
Packit 6c4009
Packit 6c4009
   The unwind information starts a byte before __restore_rt, so that
Packit 6c4009
   it is found when unwinding, to get an address the unwinder assumes
Packit 6c4009
   will be in the middle of a call instruction.  See the Linux kernel
Packit 6c4009
   (the i386 vsyscall, in particular) for an explanation of the complex
Packit 6c4009
   unwind information used here in order to get the traditional CFA.
Packit 6c4009
   We do not restore cs - it's only stored as two bytes here so that's
Packit 6c4009
   a bit tricky.  We don't use the gas cfi directives, so that we can
Packit 6c4009
   reliably add .cfi_signal_frame.  */
Packit 6c4009
Packit 6c4009
#include "ucontext_i.h"
Packit 6c4009
Packit 6c4009
#define do_cfa_expr						\
Packit 6c4009
  "	.byte 0x0f\n"		/* DW_CFA_def_cfa_expression */	\
Packit 6c4009
  "	.uleb128 2f-1f\n"	/* length */			\
Packit 6c4009
  "1:	.byte 0x77\n"		/* DW_OP_breg7 */		\
Packit 6c4009
  "	.sleb128 " CFI_STRINGIFY (oRSP) "\n"			\
Packit 6c4009
  "	.byte 0x06\n"		/* DW_OP_deref */		\
Packit 6c4009
  "2:"
Packit 6c4009
Packit 6c4009
#define do_expr(regno, offset)					\
Packit 6c4009
  "	.byte 0x10\n"		/* DW_CFA_expression */		\
Packit 6c4009
  "	.uleb128 " CFI_STRINGIFY (regno) "\n"			\
Packit 6c4009
  "	.uleb128 2f-1f\n"	/* length */			\
Packit 6c4009
  "1:	.byte 0x77\n"		/* DW_OP_breg7 */		\
Packit 6c4009
  "	.sleb128 " CFI_STRINGIFY (offset) "\n"			\
Packit 6c4009
  "2:"
Packit 6c4009
Packit 6c4009
#define RESTORE(name, syscall) RESTORE2 (name, syscall)
Packit 6c4009
# define RESTORE2(name, syscall) \
Packit 6c4009
asm									\
Packit 6c4009
  (									\
Packit 6c4009
   /* `nop' for debuggers assuming `call' should not disalign the code.  */ \
Packit 6c4009
   "	nop\n"								\
Packit 6c4009
   ".align 16\n"							\
Packit 6c4009
   ".LSTART_" #name ":\n"						\
Packit 6c4009
   "	.type __" #name ",@function\n"					\
Packit 6c4009
   "__" #name ":\n"							\
Packit 6c4009
   "	movq $" #syscall ", %rax\n"					\
Packit 6c4009
   "	syscall\n"							\
Packit 6c4009
   ".LEND_" #name ":\n"							\
Packit 6c4009
   ".section .eh_frame,\"a\",@progbits\n"				\
Packit 6c4009
   ".LSTARTFRAME_" #name ":\n"						\
Packit 6c4009
   "	.long .LENDCIE_" #name "-.LSTARTCIE_" #name "\n"		\
Packit 6c4009
   ".LSTARTCIE_" #name ":\n"						\
Packit 6c4009
   "	.long 0\n"	/* CIE ID */					\
Packit 6c4009
   "	.byte 1\n"	/* Version number */				\
Packit 6c4009
   "	.string \"zRS\"\n" /* NUL-terminated augmentation string */	\
Packit 6c4009
   "	.uleb128 1\n"	/* Code alignment factor */			\
Packit 6c4009
   "	.sleb128 -8\n"	/* Data alignment factor */			\
Packit 6c4009
   "	.uleb128 16\n"	/* Return address register column (rip) */	\
Packit 6c4009
   /* Augmentation value length */					\
Packit 6c4009
   "	.uleb128 .LENDAUGMNT_" #name "-.LSTARTAUGMNT_" #name "\n"	\
Packit 6c4009
   ".LSTARTAUGMNT_" #name ":\n"						\
Packit 6c4009
   "	.byte 0x1b\n"	/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */		\
Packit 6c4009
   ".LENDAUGMNT_" #name ":\n"						\
Packit 6c4009
   "	.align " LP_SIZE "\n"						\
Packit 6c4009
   ".LENDCIE_" #name ":\n"						\
Packit 6c4009
   "	.long .LENDFDE_" #name "-.LSTARTFDE_" #name "\n" /* FDE len */	\
Packit 6c4009
   ".LSTARTFDE_" #name ":\n"						\
Packit 6c4009
   "	.long .LSTARTFDE_" #name "-.LSTARTFRAME_" #name "\n" /* CIE */	\
Packit 6c4009
   /* `LSTART_' is subtracted 1 as debuggers assume a `call' here.  */	\
Packit 6c4009
   "	.long (.LSTART_" #name "-1)-.\n" /* PC-relative start addr.  */	\
Packit 6c4009
   "	.long .LEND_" #name "-(.LSTART_" #name "-1)\n"			\
Packit 6c4009
   "	.uleb128 0\n"			/* FDE augmentation length */	\
Packit 6c4009
   do_cfa_expr								\
Packit 6c4009
   do_expr (8 /* r8 */, oR8)						\
Packit 6c4009
   do_expr (9 /* r9 */, oR9)						\
Packit 6c4009
   do_expr (10 /* r10 */, oR10)						\
Packit 6c4009
   do_expr (11 /* r11 */, oR11)						\
Packit 6c4009
   do_expr (12 /* r12 */, oR12)						\
Packit 6c4009
   do_expr (13 /* r13 */, oR13)						\
Packit 6c4009
   do_expr (14 /* r14 */, oR14)						\
Packit 6c4009
   do_expr (15 /* r15 */, oR15)						\
Packit 6c4009
   do_expr (5 /* rdi */, oRDI)						\
Packit 6c4009
   do_expr (4 /* rsi */, oRSI)						\
Packit 6c4009
   do_expr (6 /* rbp */, oRBP)						\
Packit 6c4009
   do_expr (3 /* rbx */, oRBX)						\
Packit 6c4009
   do_expr (1 /* rdx */, oRDX)						\
Packit 6c4009
   do_expr (0 /* rax */, oRAX)						\
Packit 6c4009
   do_expr (2 /* rcx */, oRCX)						\
Packit 6c4009
   do_expr (7 /* rsp */, oRSP)						\
Packit 6c4009
   do_expr (16 /* rip */, oRIP)						\
Packit 6c4009
   /* libgcc-4.1.1 has only `DWARF_FRAME_REGISTERS == 17'.  */		\
Packit 6c4009
   /* do_expr (49 |* rflags *|, oEFL) */				\
Packit 6c4009
   /* `cs'/`ds'/`fs' are unaligned and a different size.  */		\
Packit 6c4009
   /* gas: Error: register save offset not a multiple of 8  */		\
Packit 6c4009
   "	.align " LP_SIZE "\n"						\
Packit 6c4009
   ".LENDFDE_" #name ":\n"						\
Packit 6c4009
   "	.previous\n"							\
Packit 6c4009
   );
Packit 6c4009
/* The return code for realtime-signals.  */
Packit 6c4009
RESTORE (restore_rt, __NR_rt_sigreturn)