1999-02-19 03:21:36 +03:00
/*
* Copyright ( c ) 1991 , 1992 Paul Kranenburg < pk @ cs . few . eur . nl >
* Copyright ( c ) 1993 Branko Lankester < branko @ hacktic . nl >
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
1999-12-23 17:20:14 +03:00
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* Copyright ( c ) 1999 IBM Deutschland Entwicklung GmbH , IBM Corporation
* Linux for s390 port by D . J . Barrow
* < barrow_dj @ mail . yahoo . com , djbarrow @ de . ibm . com >
1999-02-19 03:21:36 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "defs.h"
2015-07-18 02:56:54 +03:00
# include <signal.h>
2011-08-18 14:48:56 +04:00
1999-02-19 03:21:36 +03:00
# ifndef NSIG
2015-03-06 04:47:18 +03:00
# warning NSIG is not defined, using 32
2012-02-25 05:38:52 +04:00
# define NSIG 32
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
# elif NSIG < 32
2015-03-06 04:47:18 +03:00
# error NSIG < 32
1999-02-19 03:21:36 +03:00
# endif
2011-08-18 14:48:56 +04:00
2002-12-16 02:58:41 +03:00
/* The libc headers do not define this constant since it should only be
2011-08-18 14:48:56 +04:00
used by the implementation . So we define it here . */
2014-02-08 04:26:06 +04:00
# ifndef SA_RESTORER
# ifdef ASM_SA_RESTORER
# define SA_RESTORER ASM_SA_RESTORER
2002-12-16 02:58:41 +03:00
# endif
# endif
2015-02-28 20:17:09 +03:00
/*
* Some architectures define SA_RESTORER in their headers ,
* but do not actually have sa_restorer .
*
* Some architectures , otherwise , do not define SA_RESTORER in their headers ,
* but actually have sa_restorer .
*/
# ifdef SA_RESTORER
# if defined HPPA || defined IA64
# define HAVE_SA_RESTORER 0
# else
# define HAVE_SA_RESTORER 1
# endif
# else /* !SA_RESTORER */
2015-03-11 16:15:34 +03:00
# if defined SPARC || defined SPARC64 || defined M68K
2015-02-28 20:17:09 +03:00
# define HAVE_SA_RESTORER 1
# else
# define HAVE_SA_RESTORER 0
# endif
2014-08-09 17:04:18 +04:00
# endif
2014-04-26 03:30:54 +04:00
# include "xlat/sigact_flags.h"
# include "xlat/sigprocmaskcmds.h"
1999-02-19 03:21:36 +03:00
1999-03-30 03:23:13 +04:00
/* Anonymous realtime signals. */
2015-03-05 08:03:41 +03:00
# ifndef ASM_SIGRTMIN
/* Linux kernel >= 3.18 defines SIGRTMIN to 32 on all architectures. */
# define ASM_SIGRTMIN 32
1999-03-30 03:23:13 +04:00
# endif
2015-03-05 08:03:41 +03:00
# ifndef ASM_SIGRTMAX
/* Under glibc 2.1, SIGRTMAX et al are functions, but __SIGRTMAX is a
constant . This is what we want . Otherwise , just use SIGRTMAX . */
# ifdef SIGRTMAX
# ifndef __SIGRTMAX
# define __SIGRTMAX SIGRTMAX
# endif
# endif
# ifdef __SIGRTMAX
# define ASM_SIGRTMAX __SIGRTMAX
# endif
1999-03-30 03:23:13 +04:00
# endif
Set saner MAX_ARGS (6 or 8) for X86_64 and I386
I noticed that tcp->u_args[MAX_ARGS] array is way larger than
I'd expect: for all arches except HPPA it has 32 (!) elements.
I looked at the code and so far I spotted only one abuser of
this fact: sys_sigreturn. On several arches, it saves sigset_t
into tcp->u_args[1...N] on entry and prints it on exit, a-la
memcpy(&tcp->u_arg[1], &sc.oldmask[0], sizeof(sigset_t))
The problem here is that in glibc sigset_t is insanely large:
128 bytes, and using sizeof(sigset_t) in memcpy will overrun
&tcp->u_args[1] even with MAX_ARGS == 32:
On 32 bits, sizeof(tcp->u_args) == 32*4 == 128 bytes!
We may already have a bug there!
This commit changes the code to save NSIG / 8 bytes only.
NSIG can't ever be > 256, and in practice is <= 129,
thus NSIG / 8 is <= 16 bytes == 4 32-bit words,
and even MAX_ARGS == 5 should be enough for saving signal masks.
* defs.h: Reduce MAX_ARGS for X86_64 and I386 from 32 to 8
for FreeBSD and to 6 for everyone else. Add comment about current
state of needed MAX_ARGS.
* signal.c: Add comment about size of sigset_t.
(sprintsigmask): Reduce static string buffer from 8k to 2k.
(sys_sigreturn): Fix sigset saving to save only NSIG / 8 bytes,
not sizeof(sigset_t) bytes.
* linux/mips/syscallent.h: Reduce nargs of printargs-type syscall to 7.
* linux/arm/syscallent.h: Reduce nargs of printargs-type syscall to 6.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-19 19:41:28 +04:00
/* Note on the size of sigset_t:
*
* In glibc , sigset_t is an array with space for 1024 bits ( ! ) ,
* even though all arches supported by Linux have only 64 signals
* except MIPS , which has 128. IOW , it is 128 bytes long .
*
* In - kernel sigset_t is sized correctly ( it is either 64 or 128 bit long ) .
* However , some old syscall return only 32 lower bits ( one word ) .
* Example : sys_sigpending vs sys_rt_sigpending .
*
* Be aware of this fact when you try to
* memcpy ( & tcp - > u_arg [ 1 ] , & something , sizeof ( sigset_t ) )
* - sizeof ( sigset_t ) is much bigger than you think ,
* it may overflow tcp - > u_arg [ ] array , and it may try to copy more data
* than is really available in < something > .
* Similarly ,
* umoven ( tcp , addr , sizeof ( sigset_t ) , & sigset )
* may be a bad idea : it ' ll try to read much more data than needed
* to fetch a sigset_t .
* Use ( NSIG / 8 ) as a size instead .
*/
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
const char *
2014-09-10 17:46:04 +04:00
signame ( const int sig )
1999-03-30 03:23:13 +04:00
{
2014-09-10 17:46:04 +04:00
static char buf [ sizeof ( " SIGRT_%u " ) + sizeof ( int ) * 3 ] ;
2011-08-18 14:48:56 +04:00
2014-09-10 17:46:04 +04:00
if ( sig > = 0 ) {
const unsigned int s = sig ;
if ( s < nsignals )
return signalent [ s ] ;
2015-03-05 08:03:41 +03:00
# ifdef ASM_SIGRTMAX
if ( s > = ASM_SIGRTMIN & & s < = ASM_SIGRTMAX ) {
sprintf ( buf , " SIGRT_%u " , s - ASM_SIGRTMIN ) ;
2014-09-10 17:46:04 +04:00
return buf ;
}
2011-08-18 14:48:56 +04:00
# endif
2014-09-10 17:46:04 +04:00
}
2011-08-18 14:48:56 +04:00
sprintf ( buf , " %d " , sig ) ;
return buf ;
1999-03-30 03:23:13 +04:00
}
1999-02-19 03:21:36 +03:00
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
static unsigned int
popcount32 ( const uint32_t * a , unsigned int size )
1999-02-19 03:21:36 +03:00
{
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
unsigned int count = 0 ;
Set saner MAX_ARGS (6 or 8) for X86_64 and I386
I noticed that tcp->u_args[MAX_ARGS] array is way larger than
I'd expect: for all arches except HPPA it has 32 (!) elements.
I looked at the code and so far I spotted only one abuser of
this fact: sys_sigreturn. On several arches, it saves sigset_t
into tcp->u_args[1...N] on entry and prints it on exit, a-la
memcpy(&tcp->u_arg[1], &sc.oldmask[0], sizeof(sigset_t))
The problem here is that in glibc sigset_t is insanely large:
128 bytes, and using sizeof(sigset_t) in memcpy will overrun
&tcp->u_args[1] even with MAX_ARGS == 32:
On 32 bits, sizeof(tcp->u_args) == 32*4 == 128 bytes!
We may already have a bug there!
This commit changes the code to save NSIG / 8 bytes only.
NSIG can't ever be > 256, and in practice is <= 129,
thus NSIG / 8 is <= 16 bytes == 4 32-bit words,
and even MAX_ARGS == 5 should be enough for saving signal masks.
* defs.h: Reduce MAX_ARGS for X86_64 and I386 from 32 to 8
for FreeBSD and to 6 for everyone else. Add comment about current
state of needed MAX_ARGS.
* signal.c: Add comment about size of sigset_t.
(sprintsigmask): Reduce static string buffer from 8k to 2k.
(sys_sigreturn): Fix sigset saving to save only NSIG / 8 bytes,
not sizeof(sigset_t) bytes.
* linux/mips/syscallent.h: Reduce nargs of printargs-type syscall to 7.
* linux/arm/syscallent.h: Reduce nargs of printargs-type syscall to 6.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-19 19:41:28 +04:00
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
for ( ; size ; + + a , - - size ) {
uint32_t x = * a ;
1999-02-19 03:21:36 +03:00
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
# ifdef HAVE___BUILTIN_POPCOUNT
count + = __builtin_popcount ( x ) ;
2013-07-18 22:42:41 +04:00
# else
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
for ( ; x ; + + count )
x & = x - 1 ;
1999-04-06 05:19:39 +04:00
# endif
1999-02-19 03:21:36 +03:00
}
2012-01-30 01:38:35 +04:00
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
return count ;
}
2015-03-06 04:47:18 +03:00
const char *
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
sprintsigmask_n ( const char * prefix , const void * sig_mask , unsigned int bytes )
{
/*
* The maximum number of signal names to be printed is NSIG * 2 / 3.
* Most of signal names have length 7 ,
* average length of signal names is less than 7.
* The length of prefix string does not exceed 16.
*/
static char outstr [ 128 + 8 * ( NSIG * 2 / 3 ) ] ;
char * s ;
const uint32_t * mask ;
uint32_t inverted_mask [ NSIG / 32 ] ;
unsigned int size ;
int i ;
char sep ;
s = stpcpy ( outstr , prefix ) ;
mask = sig_mask ;
/* length of signal mask in 4-byte words */
size = ( bytes > = NSIG / 8 ) ? NSIG / 32 : ( bytes + 3 ) / 4 ;
/* check whether 2/3 or more bits are set */
if ( popcount32 ( mask , size ) > = size * 32 * 2 / 3 ) {
/* show those signals that are NOT in the mask */
unsigned int j ;
for ( j = 0 ; j < size ; + + j )
inverted_mask [ j ] = ~ mask [ j ] ;
mask = inverted_mask ;
1999-02-19 03:21:36 +03:00
* s + + = ' ~ ' ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
}
2012-01-30 01:38:35 +04:00
sep = ' [ ' ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
for ( i = 0 ; ( i = next_set_bit ( mask , i , size * 32 ) ) > = 0 ; ) {
+ + i ;
* s + + = sep ;
2014-09-10 17:46:04 +04:00
if ( ( unsigned ) i < nsignals ) {
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
s = stpcpy ( s , signalent [ i ] + 3 ) ;
}
2015-03-05 08:03:41 +03:00
# ifdef ASM_SIGRTMAX
else if ( i > = ASM_SIGRTMIN & & i < = ASM_SIGRTMAX ) {
s + = sprintf ( s , " RT_%u " , i - ASM_SIGRTMIN ) ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
}
2013-07-18 22:42:41 +04:00
# endif
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
else {
s + = sprintf ( s , " %u " , i ) ;
1999-02-19 03:21:36 +03:00
}
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
sep = ' ' ;
1999-02-19 03:21:36 +03:00
}
2012-01-30 01:38:35 +04:00
if ( sep = = ' [ ' )
* s + + = sep ;
1999-02-19 03:21:36 +03:00
* s + + = ' ] ' ;
* s = ' \0 ' ;
return outstr ;
}
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
# define sprintsigmask_val(prefix, mask) \
sprintsigmask_n ( ( prefix ) , & ( mask ) , sizeof ( mask ) )
# define tprintsigmask_val(prefix, mask) \
tprints ( sprintsigmask_n ( ( prefix ) , & ( mask ) , sizeof ( mask ) ) )
1999-02-19 03:21:36 +03:00
void
2011-06-09 03:28:11 +04:00
printsignal ( int nr )
1999-02-19 03:21:36 +03:00
{
2011-09-01 11:55:05 +04:00
tprints ( signame ( nr ) ) ;
1999-02-19 03:21:36 +03:00
}
2006-10-13 Ulrich Drepper <drepper@redhat.com>
Bernhard Kaindl <bk@suse.de>
Dmitry V. Levin <ldv@altlinux.org>
Michael Holzheu <holzheu@de.ibm.com>
Add hooks for new syscalls. Add decoders for *at, inotify*,
pselect6, ppoll and unshare syscalls.
* defs.h: Declare print_sigset.
* desc.c (sys_pselect6): New function.
* file.c (decode_open, decode_access, decode_mkdir,
decode_readlink, decode_chmod, decode_utimes, decode_mknod):
New functions.
(sys_open, sys_access, sys_mkdir, sys_readlink, sys_chmod,
sys_utimes, sys_mknod): Use them.
[LINUX] (fstatatflags, unlinkatflags, inotify_modes): New
variables.
[LINUX] (print_dirfd, sys_openat, sys_faccessat,
sys_newfstatat, sys_mkdirat, sys_linkat, sys_unlinkat,
sys_symlinkat, sys_readlinkat, sys_renameat, sys_fchownat,
sys_fchmodat, sys_futimesat, sys_mknodat, sys_inotify_add_watch,
sys_inotify_rm_watch): New functions.
* process.c [LINUX] (sys_unshare): New function.
* signal.c (print_sigset): New function.
(sys_sigprocmask): Use it.
* stream.c (decode_poll): New function.
(sys_poll): Use it.
[LINUX] (sys_ppoll): New function.
* linux/syscall.h: Delcare new syscall handlers.
* linux/syscallent.h: Hook up new syscalls.
* linux/alpha/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Fixes RH#178633.
2006-10-14 00:25:12 +04:00
void
2013-07-18 19:02:21 +04:00
print_sigset_addr_len ( struct tcb * tcp , long addr , long len )
2006-10-13 Ulrich Drepper <drepper@redhat.com>
Bernhard Kaindl <bk@suse.de>
Dmitry V. Levin <ldv@altlinux.org>
Michael Holzheu <holzheu@de.ibm.com>
Add hooks for new syscalls. Add decoders for *at, inotify*,
pselect6, ppoll and unshare syscalls.
* defs.h: Declare print_sigset.
* desc.c (sys_pselect6): New function.
* file.c (decode_open, decode_access, decode_mkdir,
decode_readlink, decode_chmod, decode_utimes, decode_mknod):
New functions.
(sys_open, sys_access, sys_mkdir, sys_readlink, sys_chmod,
sys_utimes, sys_mknod): Use them.
[LINUX] (fstatatflags, unlinkatflags, inotify_modes): New
variables.
[LINUX] (print_dirfd, sys_openat, sys_faccessat,
sys_newfstatat, sys_mkdirat, sys_linkat, sys_unlinkat,
sys_symlinkat, sys_readlinkat, sys_renameat, sys_fchownat,
sys_fchmodat, sys_futimesat, sys_mknodat, sys_inotify_add_watch,
sys_inotify_rm_watch): New functions.
* process.c [LINUX] (sys_unshare): New function.
* signal.c (print_sigset): New function.
(sys_sigprocmask): Use it.
* stream.c (decode_poll): New function.
(sys_poll): Use it.
[LINUX] (sys_ppoll): New function.
* linux/syscall.h: Delcare new syscall handlers.
* linux/syscallent.h: Hook up new syscalls.
* linux/alpha/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Fixes RH#178633.
2006-10-14 00:25:12 +04:00
{
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
char mask [ NSIG / 8 ] ;
2006-10-13 Ulrich Drepper <drepper@redhat.com>
Bernhard Kaindl <bk@suse.de>
Dmitry V. Levin <ldv@altlinux.org>
Michael Holzheu <holzheu@de.ibm.com>
Add hooks for new syscalls. Add decoders for *at, inotify*,
pselect6, ppoll and unshare syscalls.
* defs.h: Declare print_sigset.
* desc.c (sys_pselect6): New function.
* file.c (decode_open, decode_access, decode_mkdir,
decode_readlink, decode_chmod, decode_utimes, decode_mknod):
New functions.
(sys_open, sys_access, sys_mkdir, sys_readlink, sys_chmod,
sys_utimes, sys_mknod): Use them.
[LINUX] (fstatatflags, unlinkatflags, inotify_modes): New
variables.
[LINUX] (print_dirfd, sys_openat, sys_faccessat,
sys_newfstatat, sys_mkdirat, sys_linkat, sys_unlinkat,
sys_symlinkat, sys_readlinkat, sys_renameat, sys_fchownat,
sys_fchmodat, sys_futimesat, sys_mknodat, sys_inotify_add_watch,
sys_inotify_rm_watch): New functions.
* process.c [LINUX] (sys_unshare): New function.
* signal.c (print_sigset): New function.
(sys_sigprocmask): Use it.
* stream.c (decode_poll): New function.
(sys_poll): Use it.
[LINUX] (sys_ppoll): New function.
* linux/syscall.h: Delcare new syscall handlers.
* linux/syscallent.h: Hook up new syscalls.
* linux/alpha/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Fixes RH#178633.
2006-10-14 00:25:12 +04:00
2013-07-18 19:02:21 +04:00
/* Here len is usually equals NSIG / 8 or current_wordsize.
* But we code this defensively :
*/
if ( len < 0 ) {
2015-07-17 03:37:39 +03:00
printaddr ( addr ) ;
2013-07-18 19:02:21 +04:00
return ;
}
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
if ( len > = NSIG / 8 )
2013-07-18 19:02:21 +04:00
len = NSIG / 8 ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
else
len = ( len + 3 ) & ~ 3 ;
2015-07-17 03:37:39 +03:00
if ( umoven_or_printaddr ( tcp , addr , len , mask ) )
return ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprints ( sprintsigmask_n ( " " , mask , len ) ) ;
2006-10-13 Ulrich Drepper <drepper@redhat.com>
Bernhard Kaindl <bk@suse.de>
Dmitry V. Levin <ldv@altlinux.org>
Michael Holzheu <holzheu@de.ibm.com>
Add hooks for new syscalls. Add decoders for *at, inotify*,
pselect6, ppoll and unshare syscalls.
* defs.h: Declare print_sigset.
* desc.c (sys_pselect6): New function.
* file.c (decode_open, decode_access, decode_mkdir,
decode_readlink, decode_chmod, decode_utimes, decode_mknod):
New functions.
(sys_open, sys_access, sys_mkdir, sys_readlink, sys_chmod,
sys_utimes, sys_mknod): Use them.
[LINUX] (fstatatflags, unlinkatflags, inotify_modes): New
variables.
[LINUX] (print_dirfd, sys_openat, sys_faccessat,
sys_newfstatat, sys_mkdirat, sys_linkat, sys_unlinkat,
sys_symlinkat, sys_readlinkat, sys_renameat, sys_fchownat,
sys_fchmodat, sys_futimesat, sys_mknodat, sys_inotify_add_watch,
sys_inotify_rm_watch): New functions.
* process.c [LINUX] (sys_unshare): New function.
* signal.c (print_sigset): New function.
(sys_sigprocmask): Use it.
* stream.c (decode_poll): New function.
(sys_poll): Use it.
[LINUX] (sys_ppoll): New function.
* linux/syscall.h: Delcare new syscall handlers.
* linux/syscallent.h: Hook up new syscalls.
* linux/alpha/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Fixes RH#178633.
2006-10-14 00:25:12 +04:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( sigsetmask )
1999-02-19 03:21:36 +03:00
{
if ( entering ( tcp ) ) {
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprintsigmask_val ( " " , tcp - > u_arg [ 0 ] ) ;
1999-02-19 03:21:36 +03:00
}
else if ( ! syserror ( tcp ) ) {
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tcp - > auxstr = sprintsigmask_val ( " old mask " , tcp - > u_rval ) ;
1999-02-19 03:21:36 +03:00
return RVAL_HEX | RVAL_STR ;
}
return 0 ;
}
# ifdef HAVE_SIGACTION
struct old_sigaction {
2013-02-08 15:59:13 +04:00
/* sa_handler may be a libc #define, need to use other name: */
2013-12-10 07:58:42 +04:00
# ifdef MIPS
unsigned int sa_flags ;
void ( * __sa_handler ) ( int ) ;
/* Kernel treats sa_mask as an array of longs. */
unsigned long sa_mask [ NSIG / sizeof ( long ) ? NSIG / sizeof ( long ) : 1 ] ;
# else
2013-02-08 15:59:13 +04:00
void ( * __sa_handler ) ( int ) ;
1999-02-19 03:21:36 +03:00
unsigned long sa_mask ;
unsigned long sa_flags ;
2013-12-10 07:58:42 +04:00
# endif /* !MIPS */
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER
2014-09-11 23:05:18 +04:00
void ( * sa_restorer ) ( void ) ;
# endif
1999-02-19 03:21:36 +03:00
} ;
2014-03-01 03:21:35 +04:00
struct old_sigaction32 {
/* sa_handler may be a libc #define, need to use other name: */
uint32_t __sa_handler ;
uint32_t sa_mask ;
uint32_t sa_flags ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER
2014-03-01 03:21:35 +04:00
uint32_t sa_restorer ;
2014-09-11 23:05:18 +04:00
# endif
2014-03-01 03:21:35 +04:00
} ;
2014-01-08 02:41:30 +04:00
static void
decode_old_sigaction ( struct tcb * tcp , long addr )
1999-02-19 03:21:36 +03:00
{
struct old_sigaction sa ;
2014-03-01 03:21:35 +04:00
# if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
if ( current_wordsize ! = sizeof ( sa . __sa_handler ) & & current_wordsize = = 4 ) {
struct old_sigaction32 sa32 ;
2015-07-17 03:37:39 +03:00
if ( umove_or_printaddr ( tcp , addr , & sa32 ) )
return ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
sa . __sa_handler = ( void * ) ( uintptr_t ) sa32 . __sa_handler ;
sa . sa_flags = sa32 . sa_flags ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER && defined SA_RESTORER
2015-07-17 03:37:39 +03:00
sa . sa_restorer = ( void * ) ( uintptr_t ) sa32 . sa_restorer ;
2014-09-11 23:05:18 +04:00
# endif
2015-07-17 03:37:39 +03:00
sa . sa_mask = sa32 . sa_mask ;
2014-03-01 03:21:35 +04:00
} else
# endif
2015-07-17 03:37:39 +03:00
if ( umove_or_printaddr ( tcp , addr , & sa ) )
2014-01-08 02:41:30 +04:00
return ;
/* Architectures using function pointers, like
* hppa , may need to manipulate the function pointer
* to compute the result of a comparison . However ,
* the __sa_handler function pointer exists only in
* the address space of the traced process , and can ' t
* be manipulated by strace . In order to prevent the
* compiler from generating code to manipulate
* __sa_handler we cast the function pointers to long . */
2015-07-17 03:37:39 +03:00
tprints ( " { " ) ;
2014-01-08 02:41:30 +04:00
if ( ( long ) sa . __sa_handler = = ( long ) SIG_ERR )
2015-07-17 03:37:39 +03:00
tprints ( " SIG_ERR " ) ;
2014-01-08 02:41:30 +04:00
else if ( ( long ) sa . __sa_handler = = ( long ) SIG_DFL )
2015-07-17 03:37:39 +03:00
tprints ( " SIG_DFL " ) ;
2014-01-08 02:41:30 +04:00
else if ( ( long ) sa . __sa_handler = = ( long ) SIG_IGN )
2015-07-17 03:37:39 +03:00
tprints ( " SIG_IGN " ) ;
2014-01-08 02:41:30 +04:00
else
2015-07-17 03:37:39 +03:00
printaddr ( ( long ) sa . __sa_handler ) ;
tprints ( " , " ) ;
2013-12-10 07:58:42 +04:00
# ifdef MIPS
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprintsigmask_addr ( " " , sa . sa_mask ) ;
2013-12-10 07:58:42 +04:00
# else
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprintsigmask_val ( " " , sa . sa_mask ) ;
2013-12-10 07:58:42 +04:00
# endif
2014-01-08 02:41:30 +04:00
tprints ( " , " ) ;
printflags ( sigact_flags , sa . sa_flags , " SA_??? " ) ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER && defined SA_RESTORER
2014-01-08 02:41:30 +04:00
if ( sa . sa_flags & SA_RESTORER )
tprintf ( " , %p " , sa . sa_restorer ) ;
2002-12-16 02:58:41 +03:00
# endif
2014-01-08 02:41:30 +04:00
tprints ( " } " ) ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( sigaction )
2014-01-08 02:41:30 +04:00
{
if ( entering ( tcp ) ) {
printsignal ( tcp - > u_arg [ 0 ] ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2014-01-08 02:41:30 +04:00
decode_old_sigaction ( tcp , tcp - > u_arg [ 1 ] ) ;
tprints ( " , " ) ;
} else
decode_old_sigaction ( tcp , tcp - > u_arg [ 2 ] ) ;
1999-02-19 03:21:36 +03:00
return 0 ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( signal )
1999-02-19 03:21:36 +03:00
{
if ( entering ( tcp ) ) {
printsignal ( tcp - > u_arg [ 0 ] ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
1999-02-19 03:21:36 +03:00
switch ( tcp - > u_arg [ 1 ] ) {
2008-08-07 01:38:52 +04:00
case ( long ) SIG_ERR :
2011-09-01 12:00:28 +04:00
tprints ( " SIG_ERR " ) ;
1999-02-19 03:21:36 +03:00
break ;
2008-08-07 01:38:52 +04:00
case ( long ) SIG_DFL :
2011-09-01 12:00:28 +04:00
tprints ( " SIG_DFL " ) ;
1999-02-19 03:21:36 +03:00
break ;
2008-08-07 01:38:52 +04:00
case ( long ) SIG_IGN :
2011-09-01 12:00:28 +04:00
tprints ( " SIG_IGN " ) ;
1999-02-19 03:21:36 +03:00
break ;
default :
2015-07-17 03:37:39 +03:00
printaddr ( tcp - > u_arg [ 1 ] ) ;
1999-02-19 03:21:36 +03:00
}
2000-08-10 06:14:04 +04:00
return 0 ;
}
2008-09-03 05:22:18 +04:00
else if ( ! syserror ( tcp ) ) {
2000-08-10 06:14:04 +04:00
switch ( tcp - > u_rval ) {
2012-03-17 07:42:07 +04:00
case ( long ) SIG_ERR :
2000-08-10 06:14:04 +04:00
tcp - > auxstr = " SIG_ERR " ; break ;
2012-03-17 07:42:07 +04:00
case ( long ) SIG_DFL :
2000-08-10 06:14:04 +04:00
tcp - > auxstr = " SIG_DFL " ; break ;
2012-03-17 07:42:07 +04:00
case ( long ) SIG_IGN :
2000-08-10 06:14:04 +04:00
tcp - > auxstr = " SIG_IGN " ; break ;
2012-03-17 07:42:07 +04:00
default :
2000-08-10 06:14:04 +04:00
tcp - > auxstr = NULL ;
}
return RVAL_HEX | RVAL_STR ;
}
2008-09-03 05:22:18 +04:00
return 0 ;
2000-08-10 06:14:04 +04:00
}
1999-02-19 03:21:36 +03:00
# endif /* HAVE_SIGACTION */
2015-04-07 04:36:50 +03:00
SYS_FUNC ( siggetmask )
1999-02-19 03:21:36 +03:00
{
if ( exiting ( tcp ) ) {
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tcp - > auxstr = sprintsigmask_val ( " mask " , tcp - > u_rval ) ;
1999-02-19 03:21:36 +03:00
}
return RVAL_HEX | RVAL_STR ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( sigsuspend )
1999-02-19 03:21:36 +03:00
{
2015-07-17 03:51:45 +03:00
tprintsigmask_val ( " " , tcp - > u_arg [ 2 ] ) ;
return RVAL_DECODED ;
1999-02-19 03:21:36 +03:00
}
# ifdef HAVE_SIGACTION
2013-07-18 19:02:21 +04:00
/* "Old" sigprocmask, which operates with word-sized signal masks */
2015-04-07 04:36:50 +03:00
SYS_FUNC ( sigprocmask )
1999-02-19 03:21:36 +03:00
{
2013-07-18 19:02:21 +04:00
# ifdef ALPHA
1999-02-19 03:21:36 +03:00
if ( entering ( tcp ) ) {
alpha: fix decode of osf_sigprocmask
The alpha sigprocmask syscall is special in that it comes from OSF rather
than the style that everyone else uses.
Tested with this simple code:
$ cat test.c
#include <signal.h>
main() {
sigset_t set, oldset;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGHUP);
sigprocmask(SIG_SETMASK, &set, &oldset);
sigprocmask(SIG_UNBLOCK, &oldset, &set);
sleep(3);
}
$ gcc test.c && ./strace ./a.out
...
osf_sigprocmask(SIG_SETMASK, [HUP INT]) = 0 (old mask [])
osf_sigprocmask(SIG_UNBLOCK, []) = 0x3 (old mask [HUP INT])
osf_sigprocmask(SIG_BLOCK, [CHLD]) = 0x3 (old mask [HUP INT])
...
* linux/alpha/syscallent.h: Call sys_sigprocmask for osf_sigprocmask,
and change number of arguments to two.
* signal.c (sys_sigprocmask): Fix decoding of alpha osf sigprocmask.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2012-03-15 08:45:33 +04:00
/*
* Alpha / OSF is different : it doesn ' t pass in two pointers ,
* but rather passes in the new bitmask as an argument and
* then returns the old bitmask . This " works " because we
* only have 64 signals to worry about . If you want more ,
* use of the rt_sigprocmask syscall is required .
* Alpha :
* old = osf_sigprocmask ( how , new ) ;
* Everyone else :
* ret = sigprocmask ( how , & new , & old , . . . ) ;
*/
1999-02-19 03:21:36 +03:00
printxval ( sigprocmaskcmds , tcp - > u_arg [ 0 ] , " SIG_??? " ) ;
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprintsigmask_val ( " , " , tcp - > u_arg [ 1 ] ) ;
1999-02-19 03:21:36 +03:00
}
else if ( ! syserror ( tcp ) ) {
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tcp - > auxstr = sprintsigmask_val ( " old mask " , tcp - > u_rval ) ;
1999-02-19 03:21:36 +03:00
return RVAL_HEX | RVAL_STR ;
}
2013-07-18 19:02:21 +04:00
# else /* !ALPHA */
1999-02-19 03:21:36 +03:00
if ( entering ( tcp ) ) {
printxval ( sigprocmaskcmds , tcp - > u_arg [ 0 ] , " SIG_??? " ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2013-07-18 19:02:21 +04:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 1 ] , current_wordsize ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
1999-02-19 03:21:36 +03:00
}
else {
2015-07-17 03:37:39 +03:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 2 ] , current_wordsize ) ;
1999-02-19 03:21:36 +03:00
}
2013-07-18 19:02:21 +04:00
# endif /* !ALPHA */
1999-02-19 03:21:36 +03:00
return 0 ;
}
# endif /* HAVE_SIGACTION */
2015-04-07 04:36:50 +03:00
SYS_FUNC ( kill )
1999-02-19 03:21:36 +03:00
{
2015-07-17 03:51:45 +03:00
tprintf ( " %ld, %s " ,
widen_to_long ( tcp - > u_arg [ 0 ] ) ,
signame ( tcp - > u_arg [ 1 ] ) ) ;
return RVAL_DECODED ;
1999-02-19 03:21:36 +03:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( tgkill )
2003-07-09 13:47:49 +04:00
{
2015-07-17 03:51:45 +03:00
tprintf ( " %ld, %ld, %s " ,
widen_to_long ( tcp - > u_arg [ 0 ] ) ,
widen_to_long ( tcp - > u_arg [ 1 ] ) ,
signame ( tcp - > u_arg [ 2 ] ) ) ;
return RVAL_DECODED ;
2003-07-09 13:47:49 +04:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( sigpending )
1999-02-19 03:21:36 +03:00
{
2015-07-17 03:37:39 +03:00
if ( exiting ( tcp ) )
print_sigset_addr_len ( tcp , tcp - > u_arg [ 0 ] , current_wordsize ) ;
1999-02-19 03:21:36 +03:00
return 0 ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigprocmask )
1999-02-19 03:21:36 +03:00
{
2013-07-18 19:02:21 +04:00
/* Note: arg[3] is the length of the sigset. Kernel requires NSIG / 8 */
1999-02-19 03:21:36 +03:00
if ( entering ( tcp ) ) {
printxval ( sigprocmaskcmds , tcp - > u_arg [ 0 ] , " SIG_??? " ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2013-07-18 19:02:21 +04:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_arg [ 3 ] ) ;
tprints ( " , " ) ;
1999-02-19 03:21:36 +03:00
}
else {
2015-07-17 03:37:39 +03:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 3 ] ) ;
1999-03-30 03:33:35 +04:00
tprintf ( " , %lu " , tcp - > u_arg [ 3 ] ) ;
1999-02-19 03:21:36 +03:00
}
return 0 ;
}
/* Structure describing the action to be taken when a signal arrives. */
struct new_sigaction
{
2013-02-08 15:59:13 +04:00
/* sa_handler may be a libc #define, need to use other name: */
2013-12-10 07:58:42 +04:00
# ifdef MIPS
unsigned int sa_flags ;
void ( * __sa_handler ) ( int ) ;
# else
2013-02-08 15:59:13 +04:00
void ( * __sa_handler ) ( int ) ;
1999-02-19 03:21:36 +03:00
unsigned long sa_flags ;
2013-12-10 07:58:42 +04:00
# endif /* !MIPS */
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER
2014-09-11 23:05:18 +04:00
void ( * sa_restorer ) ( void ) ;
# endif
2009-04-15 17:22:59 +04:00
/* Kernel treats sa_mask as an array of longs. */
unsigned long sa_mask [ NSIG / sizeof ( long ) ? NSIG / sizeof ( long ) : 1 ] ;
} ;
/* Same for i386-on-x86_64 and similar cases */
struct new_sigaction32
{
uint32_t __sa_handler ;
uint32_t sa_flags ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER
2009-04-15 17:22:59 +04:00
uint32_t sa_restorer ;
2014-09-11 23:05:18 +04:00
# endif
2009-04-15 17:22:59 +04:00
uint32_t sa_mask [ 2 * ( NSIG / sizeof ( long ) ? NSIG / sizeof ( long ) : 1 ) ] ;
1999-02-19 03:21:36 +03:00
} ;
2014-01-08 02:41:30 +04:00
static void
decode_new_sigaction ( struct tcb * tcp , long addr )
1999-02-19 03:21:36 +03:00
{
struct new_sigaction sa ;
2013-02-13 19:31:32 +04:00
# if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
2012-03-19 12:36:42 +04:00
if ( current_wordsize ! = sizeof ( sa . sa_flags ) & & current_wordsize = = 4 ) {
2009-04-15 17:22:59 +04:00
struct new_sigaction32 sa32 ;
2015-07-17 03:37:39 +03:00
if ( umove_or_printaddr ( tcp , addr , & sa32 ) )
return ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
sa . __sa_handler = ( void * ) ( unsigned long ) sa32 . __sa_handler ;
sa . sa_flags = sa32 . sa_flags ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER && defined SA_RESTORER
2015-07-17 03:37:39 +03:00
sa . sa_restorer = ( void * ) ( unsigned long ) sa32 . sa_restorer ;
2014-09-11 23:05:18 +04:00
# endif
2015-07-17 03:37:39 +03:00
/* Kernel treats sa_mask as an array of longs.
* For 32 - bit process , " long " is uint32_t , thus , for example ,
* 32 th bit in sa_mask will end up as bit 0 in sa_mask [ 1 ] .
* But for ( 64 - bit ) kernel , 32 th bit in sa_mask is
* 32 th bit in 0 th ( 64 - bit ) long !
* For little - endian , it ' s the same .
* For big - endian , we swap 32 - bit words .
*/
sa . sa_mask [ 0 ] = sa32 . sa_mask [ 0 ] + ( ( long ) ( sa32 . sa_mask [ 1 ] ) < < 32 ) ;
2009-04-15 17:22:59 +04:00
} else
# endif
2015-07-17 03:37:39 +03:00
if ( umove_or_printaddr ( tcp , addr , & sa ) )
2014-01-08 02:41:30 +04:00
return ;
2015-07-17 03:37:39 +03:00
2009-09-09 22:13:19 +04:00
/* Architectures using function pointers, like
* hppa , may need to manipulate the function pointer
* to compute the result of a comparison . However ,
2013-02-08 15:59:13 +04:00
* the __sa_handler function pointer exists only in
2009-09-09 22:13:19 +04:00
* the address space of the traced process , and can ' t
* be manipulated by strace . In order to prevent the
* compiler from generating code to manipulate
2013-02-08 15:59:13 +04:00
* __sa_handler we cast the function pointers to long . */
2009-09-09 22:13:19 +04:00
if ( ( long ) sa . __sa_handler = = ( long ) SIG_ERR )
2011-09-01 12:00:28 +04:00
tprints ( " {SIG_ERR, " ) ;
2009-09-09 22:13:19 +04:00
else if ( ( long ) sa . __sa_handler = = ( long ) SIG_DFL )
2011-09-01 12:00:28 +04:00
tprints ( " {SIG_DFL, " ) ;
2009-09-09 22:13:19 +04:00
else if ( ( long ) sa . __sa_handler = = ( long ) SIG_IGN )
2011-09-01 12:00:28 +04:00
tprints ( " {SIG_IGN, " ) ;
2009-04-15 17:22:59 +04:00
else
tprintf ( " {%#lx, " , ( long ) sa . __sa_handler ) ;
2013-07-18 12:10:46 +04:00
/*
* Sigset size is in tcp - > u_arg [ 4 ] ( SPARC )
* or in tcp - > u_arg [ 3 ] ( all other ) ,
* but kernel won ' t handle sys_rt_sigaction
* with wrong sigset size ( just returns EINVAL instead ) .
* We just fetch the right size , which is NSIG / 8.
*/
Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.
With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.
Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.
* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-26 20:51:28 +04:00
tprintsigmask_val ( " " , sa . sa_mask ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2013-07-18 12:10:46 +04:00
2009-04-15 17:22:59 +04:00
printflags ( sigact_flags , sa . sa_flags , " SA_??? " ) ;
2015-02-28 20:17:09 +03:00
# if HAVE_SA_RESTORER && defined SA_RESTORER
2009-04-15 17:22:59 +04:00
if ( sa . sa_flags & SA_RESTORER )
tprintf ( " , %p " , sa . sa_restorer ) ;
2002-12-16 02:58:41 +03:00
# endif
2011-09-01 12:00:28 +04:00
tprints ( " } " ) ;
2014-01-08 02:41:30 +04:00
}
2009-04-15 17:22:59 +04:00
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigaction )
2014-01-08 02:41:30 +04:00
{
if ( entering ( tcp ) ) {
printsignal ( tcp - > u_arg [ 0 ] ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2014-01-08 02:41:30 +04:00
decode_new_sigaction ( tcp , tcp - > u_arg [ 1 ] ) ;
tprints ( " , " ) ;
} else {
decode_new_sigaction ( tcp , tcp - > u_arg [ 2 ] ) ;
2013-02-12 14:43:46 +04:00
# if defined(SPARC) || defined(SPARC64)
1999-06-03 18:21:07 +04:00
tprintf ( " , %#lx, %lu " , tcp - > u_arg [ 3 ] , tcp - > u_arg [ 4 ] ) ;
# elif defined(ALPHA)
tprintf ( " , %lu, %#lx " , tcp - > u_arg [ 3 ] , tcp - > u_arg [ 4 ] ) ;
# else
2009-04-15 17:22:59 +04:00
tprintf ( " , %lu " , tcp - > u_arg [ 3 ] ) ;
1999-06-03 18:21:07 +04:00
# endif
2014-01-08 02:41:30 +04:00
}
1999-02-19 03:21:36 +03:00
return 0 ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigpending )
1999-02-19 03:21:36 +03:00
{
if ( exiting ( tcp ) ) {
2013-07-18 19:02:21 +04:00
/*
* One of the few syscalls where sigset size ( arg [ 1 ] )
* is allowed to be < = NSIG / 8 , not strictly = = .
* This allows non - rt sigpending ( ) syscall
* to reuse rt_sigpending ( ) code in kernel .
*/
2015-07-17 03:37:39 +03:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 0 ] , tcp - > u_arg [ 1 ] ) ;
2013-07-18 19:02:21 +04:00
tprintf ( " , %lu " , tcp - > u_arg [ 1 ] ) ;
1999-02-19 03:21:36 +03:00
}
return 0 ;
}
2009-04-14 16:51:00 +04:00
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigsuspend )
1999-02-19 03:21:36 +03:00
{
2015-07-17 03:51:45 +03:00
/* NB: kernel requires arg[1] == NSIG / 8 */
print_sigset_addr_len ( tcp , tcp - > u_arg [ 0 ] , tcp - > u_arg [ 1 ] ) ;
tprintf ( " , %lu " , tcp - > u_arg [ 1 ] ) ;
return RVAL_DECODED ;
1999-02-19 03:21:36 +03:00
}
2009-04-14 16:51:00 +04:00
2012-03-13 19:51:13 +04:00
static void
print_sigqueueinfo ( struct tcb * tcp , int sig , unsigned long uinfo )
{
printsignal ( sig ) ;
tprints ( " , " ) ;
2015-09-16 00:51:15 +03:00
printsiginfo_at ( tcp , uinfo ) ;
2012-03-13 19:51:13 +04:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigqueueinfo )
1999-02-19 03:21:36 +03:00
{
2015-07-17 03:51:45 +03:00
tprintf ( " %lu, " , tcp - > u_arg [ 0 ] ) ;
print_sigqueueinfo ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_arg [ 2 ] ) ;
return RVAL_DECODED ;
2012-03-13 19:51:13 +04:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_tgsigqueueinfo )
2012-03-13 19:51:13 +04:00
{
2015-07-17 03:51:45 +03:00
tprintf ( " %lu, %lu, " , tcp - > u_arg [ 0 ] , tcp - > u_arg [ 1 ] ) ;
print_sigqueueinfo ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 3 ] ) ;
return RVAL_DECODED ;
1999-02-19 03:21:36 +03:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( rt_sigtimedwait )
1999-02-19 03:21:36 +03:00
{
2013-07-18 19:02:21 +04:00
/* NB: kernel requires arg[3] == NSIG / 8 */
1999-02-19 03:21:36 +03:00
if ( entering ( tcp ) ) {
2013-07-18 19:02:21 +04:00
print_sigset_addr_len ( tcp , tcp - > u_arg [ 0 ] , tcp - > u_arg [ 3 ] ) ;
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2009-04-15 17:31:59 +04:00
/* This is the only "return" parameter, */
if ( tcp - > u_arg [ 1 ] ! = 0 )
return 0 ;
/* ... if it's NULL, can decode all on entry */
2011-09-01 12:00:28 +04:00
tprints ( " NULL, " ) ;
1999-02-19 03:21:36 +03:00
}
2009-04-15 17:31:59 +04:00
else if ( tcp - > u_arg [ 1 ] ! = 0 ) {
/* syscall exit, and u_arg[1] wasn't NULL */
2015-09-16 00:51:15 +03:00
printsiginfo_at ( tcp , tcp - > u_arg [ 1 ] ) ;
2013-02-13 19:31:32 +04:00
tprints ( " , " ) ;
1999-02-19 03:21:36 +03:00
}
2009-04-15 17:31:59 +04:00
else {
/* syscall exit, and u_arg[1] was NULL */
return 0 ;
}
2015-09-18 04:54:59 +03:00
/*
* Since the timeout parameter is read by the kernel
* on entering syscall , it has to be decoded the same way
* whether the syscall has failed or not .
*/
temporarily_clear_syserror ( tcp ) ;
2009-04-15 17:31:59 +04:00
print_timespec ( tcp , tcp - > u_arg [ 2 ] ) ;
2015-09-18 04:54:59 +03:00
restore_cleared_syserror ( tcp ) ;
2013-07-18 19:02:21 +04:00
tprintf ( " , %lu " , tcp - > u_arg [ 3 ] ) ;
1999-02-19 03:21:36 +03:00
return 0 ;
} ;
2015-04-07 04:36:50 +03:00
SYS_FUNC ( restart_syscall )
2006-01-13 01:34:50 +03:00
{
2015-07-17 03:51:45 +03:00
tprintf ( " <... resuming interrupted %s ...> " ,
tcp - > s_prev_ent ? tcp - > s_prev_ent - > sys_name : " system call " ) ;
return RVAL_DECODED ;
2006-01-13 01:34:50 +03:00
}