1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <signal.h> 30 31extern "C" void __restore_rt(void); 32extern "C" void __restore(void); 33 34#if defined(__LP64__) 35 36extern "C" int __rt_sigaction(int, const struct __kernel_sigaction*, struct __kernel_sigaction*, size_t); 37 38int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { 39 __kernel_sigaction kernel_new_action; 40 if (bionic_new_action != NULL) { 41 kernel_new_action.sa_flags = bionic_new_action->sa_flags; 42 kernel_new_action.sa_handler = bionic_new_action->sa_handler; 43 kernel_new_action.sa_mask = bionic_new_action->sa_mask; 44#if defined(SA_RESTORER) 45 kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; 46#if defined(__aarch64__) 47 // arm64 has sa_restorer, but unwinding works best if you just let the 48 // kernel supply the default restorer from [vdso]. gdb doesn't care, but 49 // libgcc needs the nop that the kernel includes before the actual code. 50 // (We could add that ourselves, but why bother?) 51#else 52 if (!(kernel_new_action.sa_flags & SA_RESTORER)) { 53 kernel_new_action.sa_flags |= SA_RESTORER; 54 kernel_new_action.sa_restorer = &__restore_rt; 55 } 56#endif 57#endif 58 } 59 60 __kernel_sigaction kernel_old_action; 61 int result = __rt_sigaction(signal, 62 (bionic_new_action != NULL) ? &kernel_new_action : NULL, 63 (bionic_old_action != NULL) ? &kernel_old_action : NULL, 64 sizeof(sigset_t)); 65 66 if (bionic_old_action != NULL) { 67 bionic_old_action->sa_flags = kernel_old_action.sa_flags; 68 bionic_old_action->sa_handler = kernel_old_action.sa_handler; 69 bionic_old_action->sa_mask = kernel_old_action.sa_mask; 70#if defined(SA_RESTORER) 71 bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; 72#endif 73 } 74 75 return result; 76} 77 78#else 79 80extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*); 81 82int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { 83 // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t, 84 // so we have to use sigaction(2) rather than rt_sigaction(2). 85 struct sigaction kernel_new_action; 86 if (bionic_new_action != NULL) { 87 kernel_new_action.sa_flags = bionic_new_action->sa_flags; 88 kernel_new_action.sa_handler = bionic_new_action->sa_handler; 89 kernel_new_action.sa_mask = bionic_new_action->sa_mask; 90#if defined(SA_RESTORER) 91 kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; 92 93 if (!(kernel_new_action.sa_flags & SA_RESTORER)) { 94 kernel_new_action.sa_flags |= SA_RESTORER; 95 kernel_new_action.sa_restorer = (kernel_new_action.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; 96 } 97#endif 98 } 99 return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action); 100} 101 102#endif 103