(root)/
strace-6.5/
src/
wait.c
       1  /*
       2   * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993-1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 2002-2004 Roland McGrath <roland@redhat.com>
       7   * Copyright (c) 2004 Ulrich Drepper <drepper@redhat.com>
       8   * Copyright (c) 2009-2013 Denys Vlasenko <dvlasenk@redhat.com>
       9   * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@strace.io>
      10   * Copyright (c) 2014-2022 The strace developers.
      11   * All rights reserved.
      12   *
      13   * SPDX-License-Identifier: LGPL-2.1-or-later
      14   */
      15  
      16  #include "defs.h"
      17  #include "ptrace.h"
      18  
      19  #include "wait.h"
      20  
      21  #include "xlat/wait4_options.h"
      22  #include "xlat/ptrace_events.h"
      23  
      24  static int
      25  printstatus(int status)
      26  {
      27  	int exited = 0;
      28  
      29  	/*
      30  	 * Here is a tricky presentation problem.  This solution
      31  	 * is still not entirely satisfactory but since there
      32  	 * are no wait status constructors it will have to do.
      33  	 */
      34  	tprint_indirect_begin();
      35  	tprint_flags_begin();
      36  	if (WIFSTOPPED(status)) {
      37  		int sig = WSTOPSIG(status);
      38  		tprintf_string("{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s}",
      39  			       sprintsigname(sig & 0x7f),
      40  			       sig & 0x80 ? " | 0x80" : "");
      41  		status &= ~W_STOPCODE(sig);
      42  	} else if (WIFSIGNALED(status)) {
      43  		tprintf_string("{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
      44  			       sprintsigname(WTERMSIG(status)),
      45  			       WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
      46  		status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
      47  	} else if (WIFEXITED(status)) {
      48  		tprintf_string("{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
      49  			       WEXITSTATUS(status));
      50  		exited = 1;
      51  		status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
      52  	}
      53  #ifdef WIFCONTINUED
      54  	else if (WIFCONTINUED(status)) {
      55  		tprints_string("{WIFCONTINUED(s)}");
      56  		status &= ~W_CONTINUED;
      57  	}
      58  #endif
      59  	else {
      60  		PRINT_VAL_X(status);
      61  		tprint_flags_end();
      62  		tprint_indirect_end();
      63  		return 0;
      64  	}
      65  
      66  	if (status) {
      67  		unsigned int event = (unsigned int) status >> 16;
      68  		if (event) {
      69  			tprint_flags_or();
      70  			tprint_shift_begin();
      71  			printxval(ptrace_events, event, "PTRACE_EVENT_???");
      72  			tprint_shift();
      73  			PRINT_VAL_U(16);
      74  			tprint_shift_end();
      75  			status &= 0xffff;
      76  		}
      77  		if (status) {
      78  			tprint_flags_or();
      79  			PRINT_VAL_X(status);
      80  		}
      81  	}
      82  	tprint_flags_end();
      83  	tprint_indirect_end();
      84  
      85  	return exited;
      86  }
      87  
      88  static int
      89  printwaitn(struct tcb *const tcp,
      90  	   void (*const print_rusage)(struct tcb *, kernel_ulong_t))
      91  {
      92  	if (entering(tcp)) {
      93  		/* pid */
      94  		printpid_tgid_pgid(tcp, tcp->u_arg[0]);
      95  		tprint_arg_next();
      96  	} else {
      97  		int status;
      98  
      99  		/* status */
     100  		if (tcp->u_rval == 0)
     101  			printaddr(tcp->u_arg[1]);
     102  		else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &status))
     103  			printstatus(status);
     104  		tprint_arg_next();
     105  
     106  		/* options */
     107  		printflags(wait4_options, tcp->u_arg[2], "W???");
     108  		if (print_rusage) {
     109  			tprint_arg_next();
     110  
     111  			/* usage */
     112  			if (tcp->u_rval > 0)
     113  				print_rusage(tcp, tcp->u_arg[3]);
     114  			else
     115  				printaddr(tcp->u_arg[3]);
     116  		}
     117  	}
     118  	return RVAL_TGID;
     119  }
     120  
     121  SYS_FUNC(waitpid)
     122  {
     123  	return printwaitn(tcp, NULL);
     124  }
     125  
     126  #if HAVE_ARCH_TIME32_SYSCALLS || HAVE_ARCH_OLD_TIME64_SYSCALLS
     127  SYS_FUNC(wait4)
     128  {
     129  	return printwaitn(tcp, printrusage);
     130  }
     131  #endif
     132  
     133  #ifdef ALPHA
     134  SYS_FUNC(osf_wait4)
     135  {
     136  	return printwaitn(tcp, printrusage32);
     137  }
     138  #endif
     139  
     140  #include "xlat/waitid_types.h"
     141  
     142  SYS_FUNC(waitid)
     143  {
     144  	unsigned int idtype = (unsigned int) tcp->u_arg[0];
     145  	int id = tcp->u_arg[1];
     146  
     147  	if (entering(tcp)) {
     148  		/* idtype */
     149  		printxval(waitid_types, idtype, "P_???");
     150  		tprint_arg_next();
     151  
     152  		switch (idtype) {
     153  		case P_PID:
     154  			printpid(tcp, id, PT_TGID);
     155  			break;
     156  		case P_PIDFD:
     157  			printfd(tcp, id);
     158  			break;
     159  		case P_PGID:
     160  			printpid(tcp, id, PT_PGID);
     161  			break;
     162  		default:
     163  			PRINT_VAL_D(id);
     164  			break;
     165  		}
     166  		tprint_arg_next();
     167  	} else {
     168  		/* siginfo */
     169  		printsiginfo_at(tcp, tcp->u_arg[2]);
     170  		tprint_arg_next();
     171  
     172  		/* options */
     173  		printflags(wait4_options, tcp->u_arg[3], "W???");
     174  		tprint_arg_next();
     175  
     176  		/* usage */
     177  		printrusage(tcp, tcp->u_arg[4]);
     178  	}
     179  	return 0;
     180  }