Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993-1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * Copyright (c) 2002-2004 Roland McGrath <roland (at) redhat.com>
      7  * Copyright (c) 2004 Ulrich Drepper <drepper (at) redhat.com>
      8  * Copyright (c) 2009-2013 Denys Vlasenko <dvlasenk (at) redhat.com>
      9  * Copyright (c) 2014-2015 Dmitry V. Levin <ldv (at) altlinux.org>
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. The name of the author may not be used to endorse or promote products
     21  *    derived from this software without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #include "defs.h"
     36 
     37 #include <sys/wait.h>
     38 
     39 #include "xlat/wait4_options.h"
     40 
     41 #if !defined WCOREFLAG && defined WCOREFLG
     42 # define WCOREFLAG WCOREFLG
     43 #endif
     44 #ifndef WCOREFLAG
     45 # define WCOREFLAG 0x80
     46 #endif
     47 #ifndef WCOREDUMP
     48 # define WCOREDUMP(status)  ((status) & 0200)
     49 #endif
     50 #ifndef W_STOPCODE
     51 # define W_STOPCODE(sig)  ((sig) << 8 | 0x7f)
     52 #endif
     53 #ifndef W_EXITCODE
     54 # define W_EXITCODE(ret, sig)  ((ret) << 8 | (sig))
     55 #endif
     56 #ifndef W_CONTINUED
     57 # define W_CONTINUED 0xffff
     58 #endif
     59 
     60 #include "ptrace.h"
     61 #include "xlat/ptrace_events.h"
     62 
     63 static int
     64 printstatus(int status)
     65 {
     66 	int exited = 0;
     67 
     68 	/*
     69 	 * Here is a tricky presentation problem.  This solution
     70 	 * is still not entirely satisfactory but since there
     71 	 * are no wait status constructors it will have to do.
     72 	 */
     73 	if (WIFSTOPPED(status)) {
     74 		int sig = WSTOPSIG(status);
     75 		tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s}",
     76 			signame(sig & 0x7f),
     77 			sig & 0x80 ? " | 0x80" : "");
     78 		status &= ~W_STOPCODE(sig);
     79 	}
     80 	else if (WIFSIGNALED(status)) {
     81 		tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
     82 			signame(WTERMSIG(status)),
     83 			WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
     84 		status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
     85 	}
     86 	else if (WIFEXITED(status)) {
     87 		tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
     88 			WEXITSTATUS(status));
     89 		exited = 1;
     90 		status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
     91 	}
     92 #ifdef WIFCONTINUED
     93 	else if (WIFCONTINUED(status)) {
     94 		tprints("[{WIFCONTINUED(s)}");
     95 		status &= ~W_CONTINUED;
     96 	}
     97 #endif
     98 	else {
     99 		tprintf("[%#x]", status);
    100 		return 0;
    101 	}
    102 
    103 	if (status) {
    104 		unsigned int event = (unsigned int) status >> 16;
    105 		if (event) {
    106 			tprints(" | ");
    107 			printxval(ptrace_events, event, "PTRACE_EVENT_???");
    108 			tprints(" << 16");
    109 			status &= 0xffff;
    110 		}
    111 		if (status)
    112 			tprintf(" | %#x", status);
    113 	}
    114 	tprints("]");
    115 
    116 	return exited;
    117 }
    118 
    119 static int
    120 printwaitn(struct tcb *tcp, int n, int bitness)
    121 {
    122 	int status;
    123 
    124 	if (entering(tcp)) {
    125 		/* On Linux, kernel-side pid_t is typedef'ed to int
    126 		 * on all arches. Also, glibc-2.8 truncates wait3 and wait4
    127 		 * pid argument to int on 64bit arches, producing,
    128 		 * for example, wait4(4294967295, ...) instead of -1
    129 		 * in strace. We have to use int here, not long.
    130 		 */
    131 		int pid = tcp->u_arg[0];
    132 		tprintf("%d, ", pid);
    133 	} else {
    134 		/* status */
    135 		if (tcp->u_rval == 0)
    136 			printaddr(tcp->u_arg[1]);
    137 		else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &status))
    138 			printstatus(status);
    139 		/* options */
    140 		tprints(", ");
    141 		printflags(wait4_options, tcp->u_arg[2], "W???");
    142 		if (n == 4) {
    143 			tprints(", ");
    144 			/* usage */
    145 			if (tcp->u_rval > 0) {
    146 #ifdef ALPHA
    147 				if (bitness)
    148 					printrusage32(tcp, tcp->u_arg[3]);
    149 				else
    150 #endif
    151 					printrusage(tcp, tcp->u_arg[3]);
    152 			}
    153 			else
    154 				printaddr(tcp->u_arg[3]);
    155 		}
    156 	}
    157 	return 0;
    158 }
    159 
    160 SYS_FUNC(waitpid)
    161 {
    162 	return printwaitn(tcp, 3, 0);
    163 }
    164 
    165 SYS_FUNC(wait4)
    166 {
    167 	return printwaitn(tcp, 4, 0);
    168 }
    169 
    170 #ifdef ALPHA
    171 SYS_FUNC(osf_wait4)
    172 {
    173 	return printwaitn(tcp, 4, 1);
    174 }
    175 #endif
    176 
    177 #include "xlat/waitid_types.h"
    178 
    179 SYS_FUNC(waitid)
    180 {
    181 	if (entering(tcp)) {
    182 		printxval(waitid_types, tcp->u_arg[0], "P_???");
    183 		tprintf(", %ld, ", tcp->u_arg[1]);
    184 	} else {
    185 		/* siginfo */
    186 		printsiginfo_at(tcp, tcp->u_arg[2]);
    187 		/* options */
    188 		tprints(", ");
    189 		printflags(wait4_options, tcp->u_arg[3], "W???");
    190 		if (tcp->s_ent->nargs > 4) {
    191 			/* usage */
    192 			tprints(", ");
    193 			printrusage(tcp, tcp->u_arg[4]);
    194 		}
    195 	}
    196 	return 0;
    197 }
    198