| 1 | /* POSIX.1 `sigaction' call for Linux/x86-64. | 
|---|
| 2 | Copyright (C) 2001-2020 Free Software Foundation, Inc. | 
|---|
| 3 | This file is part of the GNU C Library. | 
|---|
| 4 |  | 
|---|
| 5 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 6 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 7 | License as published by the Free Software Foundation; either | 
|---|
| 8 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 9 |  | 
|---|
| 10 | The GNU C Library is distributed in the hope that it will be useful, | 
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 13 | Lesser General Public License for more details. | 
|---|
| 14 |  | 
|---|
| 15 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 16 | License along with the GNU C Library; if not, see | 
|---|
| 17 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 18 |  | 
|---|
| 19 | #include <signal.h> | 
|---|
| 20 | #define SA_RESTORER 0x04000000 | 
|---|
| 21 |  | 
|---|
| 22 | extern void restore_rt (void) asm ( "__restore_rt") attribute_hidden; | 
|---|
| 23 |  | 
|---|
| 24 | #define SET_SA_RESTORER(kact, act)			\ | 
|---|
| 25 | (kact)->sa_flags = (act)->sa_flags | SA_RESTORER;	\ | 
|---|
| 26 | (kact)->sa_restorer = &restore_rt | 
|---|
| 27 |  | 
|---|
| 28 | #define RESET_SA_RESTORER(act, kact) 			\ | 
|---|
| 29 | (act)->sa_restorer = (kact)->sa_restorer | 
|---|
| 30 |  | 
|---|
| 31 | #include <kernel_sigaction.h> | 
|---|
| 32 |  | 
|---|
| 33 | #include <sysdeps/unix/sysv/linux/sigaction.c> | 
|---|
| 34 |  | 
|---|
| 35 | /* NOTE: Please think twice before making any changes to the bits of | 
|---|
| 36 | code below.  GDB needs some intimate knowledge about it to | 
|---|
| 37 | recognize them as signal trampolines, and make backtraces through | 
|---|
| 38 | signal handlers work right.  Important are both the names | 
|---|
| 39 | (__restore_rt) and the exact instruction sequence. | 
|---|
| 40 | If you ever feel the need to make any changes, please notify the | 
|---|
| 41 | appropriate GDB maintainer. | 
|---|
| 42 |  | 
|---|
| 43 | The unwind information starts a byte before __restore_rt, so that | 
|---|
| 44 | it is found when unwinding, to get an address the unwinder assumes | 
|---|
| 45 | will be in the middle of a call instruction.  See the Linux kernel | 
|---|
| 46 | (the i386 vsyscall, in particular) for an explanation of the complex | 
|---|
| 47 | unwind information used here in order to get the traditional CFA. | 
|---|
| 48 | We do not restore cs - it's only stored as two bytes here so that's | 
|---|
| 49 | a bit tricky.  We don't use the gas cfi directives, so that we can | 
|---|
| 50 | reliably add .cfi_signal_frame.  */ | 
|---|
| 51 |  | 
|---|
| 52 | #include "ucontext_i.h" | 
|---|
| 53 |  | 
|---|
| 54 | #define do_cfa_expr						\ | 
|---|
| 55 | "	.byte 0x0f\n"		/* DW_CFA_def_cfa_expression */	\ | 
|---|
| 56 | "	.uleb128 2f-1f\n"	/* length */			\ | 
|---|
| 57 | "1:	.byte 0x77\n"		/* DW_OP_breg7 */		\ | 
|---|
| 58 | "	.sleb128 " CFI_STRINGIFY (oRSP) "\n"			\ | 
|---|
| 59 | "	.byte 0x06\n"		/* DW_OP_deref */		\ | 
|---|
| 60 | "2:" | 
|---|
| 61 |  | 
|---|
| 62 | #define do_expr(regno, offset)					\ | 
|---|
| 63 | "	.byte 0x10\n"		/* DW_CFA_expression */		\ | 
|---|
| 64 | "	.uleb128 " CFI_STRINGIFY (regno) "\n"			\ | 
|---|
| 65 | "	.uleb128 2f-1f\n"	/* length */			\ | 
|---|
| 66 | "1:	.byte 0x77\n"		/* DW_OP_breg7 */		\ | 
|---|
| 67 | "	.sleb128 " CFI_STRINGIFY (offset) "\n"			\ | 
|---|
| 68 | "2:" | 
|---|
| 69 |  | 
|---|
| 70 | #define RESTORE(name, syscall) RESTORE2 (name, syscall) | 
|---|
| 71 | # define RESTORE2(name, syscall) \ | 
|---|
| 72 | asm									\ | 
|---|
| 73 | (									\ | 
|---|
| 74 | /* `nop' for debuggers assuming `call' should not disalign the code.  */ \ | 
|---|
| 75 | "	nop\n"								\ | 
|---|
| 76 | ".align 16\n"							\ | 
|---|
| 77 | ".LSTART_" #name ":\n"						\ | 
|---|
| 78 | "	.type __" #name ",@function\n"					\ | 
|---|
| 79 | "__" #name ":\n"							\ | 
|---|
| 80 | "	movq $" #syscall ", %rax\n"					\ | 
|---|
| 81 | "	syscall\n"							\ | 
|---|
| 82 | ".LEND_" #name ":\n"							\ | 
|---|
| 83 | ".section .eh_frame,\"a\",@progbits\n"				\ | 
|---|
| 84 | ".LSTARTFRAME_" #name ":\n"						\ | 
|---|
| 85 | "	.long .LENDCIE_" #name "-.LSTARTCIE_" #name "\n"		\ | 
|---|
| 86 | ".LSTARTCIE_" #name ":\n"						\ | 
|---|
| 87 | "	.long 0\n"	/* CIE ID */					\ | 
|---|
| 88 | "	.byte 1\n"	/* Version number */				\ | 
|---|
| 89 | "	.string \"zRS\"\n" /* NUL-terminated augmentation string */	\ | 
|---|
| 90 | "	.uleb128 1\n"	/* Code alignment factor */			\ | 
|---|
| 91 | "	.sleb128 -8\n"	/* Data alignment factor */			\ | 
|---|
| 92 | "	.uleb128 16\n"	/* Return address register column (rip) */	\ | 
|---|
| 93 | /* Augmentation value length */					\ | 
|---|
| 94 | "	.uleb128 .LENDAUGMNT_" #name "-.LSTARTAUGMNT_" #name "\n"	\ | 
|---|
| 95 | ".LSTARTAUGMNT_" #name ":\n"						\ | 
|---|
| 96 | "	.byte 0x1b\n"	/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */		\ | 
|---|
| 97 | ".LENDAUGMNT_" #name ":\n"						\ | 
|---|
| 98 | "	.align " LP_SIZE "\n"						\ | 
|---|
| 99 | ".LENDCIE_" #name ":\n"						\ | 
|---|
| 100 | "	.long .LENDFDE_" #name "-.LSTARTFDE_" #name "\n" /* FDE len */	\ | 
|---|
| 101 | ".LSTARTFDE_" #name ":\n"						\ | 
|---|
| 102 | "	.long .LSTARTFDE_" #name "-.LSTARTFRAME_" #name "\n" /* CIE */	\ | 
|---|
| 103 | /* `LSTART_' is subtracted 1 as debuggers assume a `call' here.  */	\ | 
|---|
| 104 | "	.long (.LSTART_" #name "-1)-.\n" /* PC-relative start addr.  */	\ | 
|---|
| 105 | "	.long .LEND_" #name "-(.LSTART_" #name "-1)\n"			\ | 
|---|
| 106 | "	.uleb128 0\n"			/* FDE augmentation length */	\ | 
|---|
| 107 | do_cfa_expr								\ | 
|---|
| 108 | do_expr (8 /* r8 */, oR8)						\ | 
|---|
| 109 | do_expr (9 /* r9 */, oR9)						\ | 
|---|
| 110 | do_expr (10 /* r10 */, oR10)						\ | 
|---|
| 111 | do_expr (11 /* r11 */, oR11)						\ | 
|---|
| 112 | do_expr (12 /* r12 */, oR12)						\ | 
|---|
| 113 | do_expr (13 /* r13 */, oR13)						\ | 
|---|
| 114 | do_expr (14 /* r14 */, oR14)						\ | 
|---|
| 115 | do_expr (15 /* r15 */, oR15)						\ | 
|---|
| 116 | do_expr (5 /* rdi */, oRDI)						\ | 
|---|
| 117 | do_expr (4 /* rsi */, oRSI)						\ | 
|---|
| 118 | do_expr (6 /* rbp */, oRBP)						\ | 
|---|
| 119 | do_expr (3 /* rbx */, oRBX)						\ | 
|---|
| 120 | do_expr (1 /* rdx */, oRDX)						\ | 
|---|
| 121 | do_expr (0 /* rax */, oRAX)						\ | 
|---|
| 122 | do_expr (2 /* rcx */, oRCX)						\ | 
|---|
| 123 | do_expr (7 /* rsp */, oRSP)						\ | 
|---|
| 124 | do_expr (16 /* rip */, oRIP)						\ | 
|---|
| 125 | /* libgcc-4.1.1 has only `DWARF_FRAME_REGISTERS == 17'.  */		\ | 
|---|
| 126 | /* do_expr (49 |* rflags *|, oEFL) */				\ | 
|---|
| 127 | /* `cs'/`ds'/`fs' are unaligned and a different size.  */		\ | 
|---|
| 128 | /* gas: Error: register save offset not a multiple of 8  */		\ | 
|---|
| 129 | "	.align " LP_SIZE "\n"						\ | 
|---|
| 130 | ".LENDFDE_" #name ":\n"						\ | 
|---|
| 131 | "	.previous\n"							\ | 
|---|
| 132 | ); | 
|---|
| 133 | /* The return code for realtime-signals.  */ | 
|---|
| 134 | RESTORE (restore_rt, __NR_rt_sigreturn) | 
|---|
| 135 |  | 
|---|