]> granicus.if.org Git - strace/blob - wait.c
process.c: move waitpid, wait4, osf_wait4, and waitid parsers to a separate file
[strace] / wait.c
1 #include "defs.h"
2
3 #include <sys/wait.h>
4
5 #ifndef __WNOTHREAD
6 # define __WNOTHREAD    0x20000000
7 #endif
8 #ifndef __WALL
9 # define __WALL         0x40000000
10 #endif
11 #ifndef __WCLONE
12 # define __WCLONE       0x80000000
13 #endif
14
15 #include "xlat/wait4_options.h"
16
17 #if !defined WCOREFLAG && defined WCOREFLG
18 # define WCOREFLAG WCOREFLG
19 #endif
20 #ifndef WCOREFLAG
21 # define WCOREFLAG 0x80
22 #endif
23 #ifndef WCOREDUMP
24 # define WCOREDUMP(status)  ((status) & 0200)
25 #endif
26 #ifndef W_STOPCODE
27 # define W_STOPCODE(sig)  ((sig) << 8 | 0x7f)
28 #endif
29 #ifndef W_EXITCODE
30 # define W_EXITCODE(ret, sig)  ((ret) << 8 | (sig))
31 #endif
32
33 static int
34 printstatus(int status)
35 {
36         int exited = 0;
37
38         /*
39          * Here is a tricky presentation problem.  This solution
40          * is still not entirely satisfactory but since there
41          * are no wait status constructors it will have to do.
42          */
43         if (WIFSTOPPED(status)) {
44                 tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s}",
45                         signame(WSTOPSIG(status)));
46                 status &= ~W_STOPCODE(WSTOPSIG(status));
47         }
48         else if (WIFSIGNALED(status)) {
49                 tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
50                         signame(WTERMSIG(status)),
51                         WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
52                 status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
53         }
54         else if (WIFEXITED(status)) {
55                 tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
56                         WEXITSTATUS(status));
57                 exited = 1;
58                 status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
59         }
60         else {
61                 tprintf("[%#x]", status);
62                 return 0;
63         }
64
65         if (status == 0)
66                 tprints("]");
67         else
68                 tprintf(" | %#x]", status);
69
70         return exited;
71 }
72
73 static int
74 printwaitn(struct tcb *tcp, int n, int bitness)
75 {
76         int status;
77
78         if (entering(tcp)) {
79                 /* On Linux, kernel-side pid_t is typedef'ed to int
80                  * on all arches. Also, glibc-2.8 truncates wait3 and wait4
81                  * pid argument to int on 64bit arches, producing,
82                  * for example, wait4(4294967295, ...) instead of -1
83                  * in strace. We have to use int here, not long.
84                  */
85                 int pid = tcp->u_arg[0];
86                 tprintf("%d, ", pid);
87         } else {
88                 /* status */
89                 if (!tcp->u_arg[1])
90                         tprints("NULL");
91                 else if (syserror(tcp) || tcp->u_rval == 0)
92                         tprintf("%#lx", tcp->u_arg[1]);
93                 else if (umove(tcp, tcp->u_arg[1], &status) < 0)
94                         tprints("[?]");
95                 else
96                         printstatus(status);
97                 /* options */
98                 tprints(", ");
99                 printflags(wait4_options, tcp->u_arg[2], "W???");
100                 if (n == 4) {
101                         tprints(", ");
102                         /* usage */
103                         if (!tcp->u_arg[3])
104                                 tprints("NULL");
105                         else if (tcp->u_rval > 0) {
106 #ifdef ALPHA
107                                 if (bitness)
108                                         printrusage32(tcp, tcp->u_arg[3]);
109                                 else
110 #endif
111                                         printrusage(tcp, tcp->u_arg[3]);
112                         }
113                         else
114                                 tprintf("%#lx", tcp->u_arg[3]);
115                 }
116         }
117         return 0;
118 }
119
120 int
121 sys_waitpid(struct tcb *tcp)
122 {
123         return printwaitn(tcp, 3, 0);
124 }
125
126 int
127 sys_wait4(struct tcb *tcp)
128 {
129         return printwaitn(tcp, 4, 0);
130 }
131
132 #ifdef ALPHA
133 int
134 sys_osf_wait4(struct tcb *tcp)
135 {
136         return printwaitn(tcp, 4, 1);
137 }
138 #endif
139
140 #include "xlat/waitid_types.h"
141
142 int
143 sys_waitid(struct tcb *tcp)
144 {
145         if (entering(tcp)) {
146                 printxval(waitid_types, tcp->u_arg[0], "P_???");
147                 tprintf(", %ld, ", tcp->u_arg[1]);
148         }
149         else {
150                 /* siginfo */
151                 printsiginfo_at(tcp, tcp->u_arg[2]);
152                 /* options */
153                 tprints(", ");
154                 printflags(wait4_options, tcp->u_arg[3], "W???");
155                 if (tcp->s_ent->nargs > 4) {
156                         /* usage */
157                         tprints(", ");
158                         if (!tcp->u_arg[4])
159                                 tprints("NULL");
160                         else if (tcp->u_error)
161                                 tprintf("%#lx", tcp->u_arg[4]);
162                         else
163                                 printrusage(tcp, tcp->u_arg[4]);
164                 }
165         }
166         return 0;
167 }