2015-12-17 20:56:48 +03:00
/*
* Copyright ( c ) 1991 , 1992 Paul Kranenburg < pk @ cs . few . eur . nl >
* Copyright ( c ) 1993 Branko Lankester < branko @ hacktic . nl >
* Copyright ( c ) 1993 - 1996 Rick Sladkey < jrs @ world . std . com >
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* Copyright ( c ) 2002 - 2004 Roland McGrath < roland @ redhat . com >
* Copyright ( c ) 2004 Ulrich Drepper < drepper @ redhat . com >
* Copyright ( c ) 2009 - 2013 Denys Vlasenko < dvlasenk @ redhat . com >
* Copyright ( c ) 2014 - 2015 Dmitry V . Levin < ldv @ altlinux . org >
2018-02-14 01:00:00 +03:00
* Copyright ( c ) 2014 - 2018 The strace developers .
2015-12-17 20:56:48 +03:00
* All rights reserved .
*
2018-12-10 03:00:00 +03:00
* SPDX - License - Identifier : LGPL - 2.1 - or - later
2015-12-17 20:56:48 +03:00
*/
2014-12-11 22:25:02 +03:00
# include "defs.h"
2018-02-11 03:26:09 +03:00
# include "ptrace.h"
2014-12-11 22:25:02 +03:00
2018-10-03 11:31:30 +03:00
# include "wait.h"
2014-12-11 22:25:02 +03:00
# include "xlat/wait4_options.h"
2015-02-13 01:43:02 +03:00
# include "xlat/ptrace_events.h"
2014-12-11 22:25:02 +03:00
static int
printstatus ( int status )
{
int exited = 0 ;
/*
* Here is a tricky presentation problem . This solution
* is still not entirely satisfactory but since there
* are no wait status constructors it will have to do .
*/
if ( WIFSTOPPED ( status ) ) {
2015-02-13 01:43:02 +03:00
int sig = WSTOPSIG ( status ) ;
tprintf ( " [{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s} " ,
2018-10-07 06:23:09 +03:00
sprintsigname ( sig & 0x7f ) ,
2015-02-13 01:43:02 +03:00
sig & 0x80 ? " | 0x80 " : " " ) ;
status & = ~ W_STOPCODE ( sig ) ;
2017-06-18 01:23:09 +03:00
} else if ( WIFSIGNALED ( status ) ) {
2014-12-11 22:25:02 +03:00
tprintf ( " [{WIFSIGNALED(s) && WTERMSIG(s) == %s%s} " ,
2018-10-07 06:23:09 +03:00
sprintsigname ( WTERMSIG ( status ) ) ,
2014-12-11 22:25:02 +03:00
WCOREDUMP ( status ) ? " && WCOREDUMP(s) " : " " ) ;
status & = ~ ( W_EXITCODE ( 0 , WTERMSIG ( status ) ) | WCOREFLAG ) ;
2017-06-18 01:23:09 +03:00
} else if ( WIFEXITED ( status ) ) {
2014-12-11 22:25:02 +03:00
tprintf ( " [{WIFEXITED(s) && WEXITSTATUS(s) == %d} " ,
WEXITSTATUS ( status ) ) ;
exited = 1 ;
status & = ~ W_EXITCODE ( WEXITSTATUS ( status ) , 0 ) ;
}
2015-02-13 01:43:02 +03:00
# ifdef WIFCONTINUED
else if ( WIFCONTINUED ( status ) ) {
tprints ( " [{WIFCONTINUED(s)} " ) ;
status & = ~ W_CONTINUED ;
}
# endif
2014-12-11 22:25:02 +03:00
else {
tprintf ( " [%#x] " , status ) ;
return 0 ;
}
2015-02-13 01:43:02 +03:00
if ( status ) {
unsigned int event = ( unsigned int ) status > > 16 ;
if ( event ) {
tprints ( " | " ) ;
printxval ( ptrace_events , event , " PTRACE_EVENT_??? " ) ;
tprints ( " << 16 " ) ;
status & = 0xffff ;
}
if ( status )
tprintf ( " | %#x " , status ) ;
}
tprints ( " ] " ) ;
2014-12-11 22:25:02 +03:00
return exited ;
}
static int
2016-12-22 03:54:18 +03:00
printwaitn ( struct tcb * const tcp ,
2016-12-26 13:26:03 +03:00
void ( * const print_rusage ) ( struct tcb * , kernel_ulong_t ) )
2014-12-11 22:25:02 +03:00
{
if ( entering ( tcp ) ) {
/* On Linux, kernel-side pid_t is typedef'ed to int
* on all arches . Also , glibc - 2.8 truncates wait3 and wait4
* pid argument to int on 64 bit arches , producing ,
* for example , wait4 ( 4294967295 , . . . ) instead of - 1
* in strace . We have to use int here , not long .
*/
int pid = tcp - > u_arg [ 0 ] ;
tprintf ( " %d, " , pid ) ;
} else {
2016-02-11 05:39:04 +03:00
int status ;
2014-12-11 22:25:02 +03:00
/* status */
2015-07-15 03:36:20 +03:00
if ( tcp - > u_rval = = 0 )
printaddr ( tcp - > u_arg [ 1 ] ) ;
else if ( ! umove_or_printaddr ( tcp , tcp - > u_arg [ 1 ] , & status ) )
2014-12-11 22:25:02 +03:00
printstatus ( status ) ;
/* options */
tprints ( " , " ) ;
printflags ( wait4_options , tcp - > u_arg [ 2 ] , " W??? " ) ;
2016-02-11 05:39:04 +03:00
if ( print_rusage ) {
2014-12-11 22:25:02 +03:00
/* usage */
2016-02-11 05:39:04 +03:00
tprints ( " , " ) ;
if ( tcp - > u_rval > 0 )
print_rusage ( tcp , tcp - > u_arg [ 3 ] ) ;
2014-12-11 22:25:02 +03:00
else
2015-07-15 03:36:20 +03:00
printaddr ( tcp - > u_arg [ 3 ] ) ;
2014-12-11 22:25:02 +03:00
}
}
return 0 ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( waitpid )
2014-12-11 22:25:02 +03:00
{
2016-02-11 05:39:04 +03:00
return printwaitn ( tcp , NULL ) ;
2014-12-11 22:25:02 +03:00
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( wait4 )
2014-12-11 22:25:02 +03:00
{
2016-02-11 05:39:04 +03:00
return printwaitn ( tcp , printrusage ) ;
2014-12-11 22:25:02 +03:00
}
# ifdef ALPHA
2015-04-07 04:36:50 +03:00
SYS_FUNC ( osf_wait4 )
2014-12-11 22:25:02 +03:00
{
2016-02-11 05:39:04 +03:00
return printwaitn ( tcp , printrusage32 ) ;
2014-12-11 22:25:02 +03:00
}
# endif
# include "xlat/waitid_types.h"
2015-04-07 04:36:50 +03:00
SYS_FUNC ( waitid )
2014-12-11 22:25:02 +03:00
{
if ( entering ( tcp ) ) {
printxval ( waitid_types , tcp - > u_arg [ 0 ] , " P_??? " ) ;
2016-02-11 05:42:36 +03:00
int pid = tcp - > u_arg [ 1 ] ;
tprintf ( " , %d, " , pid ) ;
2015-07-15 03:36:20 +03:00
} else {
2014-12-11 22:25:02 +03:00
/* siginfo */
2015-09-16 00:51:15 +03:00
printsiginfo_at ( tcp , tcp - > u_arg [ 2 ] ) ;
2014-12-11 22:25:02 +03:00
/* options */
tprints ( " , " ) ;
printflags ( wait4_options , tcp - > u_arg [ 3 ] , " W??? " ) ;
2016-02-11 05:20:18 +03:00
/* usage */
tprints ( " , " ) ;
printrusage ( tcp , tcp - > u_arg [ 4 ] ) ;
2014-12-11 22:25:02 +03:00
}
return 0 ;
}