blob: ad368d2709c171e1050a597a3d361cb0ee2469b9 [file] [log] [blame]
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +00001#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
Dmitry V. Levind8b34042015-02-12 22:43:02 +000032#ifndef W_CONTINUED
33# define W_CONTINUED 0xffff
34#endif
35
36#include "xlat/ptrace_events.h"
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000037
38static int
39printstatus(int status)
40{
41 int exited = 0;
42
43 /*
44 * Here is a tricky presentation problem. This solution
45 * is still not entirely satisfactory but since there
46 * are no wait status constructors it will have to do.
47 */
48 if (WIFSTOPPED(status)) {
Dmitry V. Levind8b34042015-02-12 22:43:02 +000049 int sig = WSTOPSIG(status);
50 tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s}",
51 signame(sig & 0x7f),
52 sig & 0x80 ? " | 0x80" : "");
53 status &= ~W_STOPCODE(sig);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000054 }
55 else if (WIFSIGNALED(status)) {
56 tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
57 signame(WTERMSIG(status)),
58 WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
59 status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
60 }
61 else if (WIFEXITED(status)) {
62 tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
63 WEXITSTATUS(status));
64 exited = 1;
65 status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
66 }
Dmitry V. Levind8b34042015-02-12 22:43:02 +000067#ifdef WIFCONTINUED
68 else if (WIFCONTINUED(status)) {
69 tprints("[{WIFCONTINUED(s)}");
70 status &= ~W_CONTINUED;
71 }
72#endif
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000073 else {
74 tprintf("[%#x]", status);
75 return 0;
76 }
77
Dmitry V. Levind8b34042015-02-12 22:43:02 +000078 if (status) {
79 unsigned int event = (unsigned int) status >> 16;
80 if (event) {
81 tprints(" | ");
82 printxval(ptrace_events, event, "PTRACE_EVENT_???");
83 tprints(" << 16");
84 status &= 0xffff;
85 }
86 if (status)
87 tprintf(" | %#x", status);
88 }
89 tprints("]");
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000090
91 return exited;
92}
93
94static int
95printwaitn(struct tcb *tcp, int n, int bitness)
96{
97 int status;
98
99 if (entering(tcp)) {
100 /* On Linux, kernel-side pid_t is typedef'ed to int
101 * on all arches. Also, glibc-2.8 truncates wait3 and wait4
102 * pid argument to int on 64bit arches, producing,
103 * for example, wait4(4294967295, ...) instead of -1
104 * in strace. We have to use int here, not long.
105 */
106 int pid = tcp->u_arg[0];
107 tprintf("%d, ", pid);
108 } else {
109 /* status */
110 if (!tcp->u_arg[1])
111 tprints("NULL");
112 else if (syserror(tcp) || tcp->u_rval == 0)
113 tprintf("%#lx", tcp->u_arg[1]);
114 else if (umove(tcp, tcp->u_arg[1], &status) < 0)
115 tprints("[?]");
116 else
117 printstatus(status);
118 /* options */
119 tprints(", ");
120 printflags(wait4_options, tcp->u_arg[2], "W???");
121 if (n == 4) {
122 tprints(", ");
123 /* usage */
124 if (!tcp->u_arg[3])
125 tprints("NULL");
126 else if (tcp->u_rval > 0) {
127#ifdef ALPHA
128 if (bitness)
129 printrusage32(tcp, tcp->u_arg[3]);
130 else
131#endif
132 printrusage(tcp, tcp->u_arg[3]);
133 }
134 else
135 tprintf("%#lx", tcp->u_arg[3]);
136 }
137 }
138 return 0;
139}
140
141int
142sys_waitpid(struct tcb *tcp)
143{
144 return printwaitn(tcp, 3, 0);
145}
146
147int
148sys_wait4(struct tcb *tcp)
149{
150 return printwaitn(tcp, 4, 0);
151}
152
153#ifdef ALPHA
154int
155sys_osf_wait4(struct tcb *tcp)
156{
157 return printwaitn(tcp, 4, 1);
158}
159#endif
160
161#include "xlat/waitid_types.h"
162
163int
164sys_waitid(struct tcb *tcp)
165{
166 if (entering(tcp)) {
167 printxval(waitid_types, tcp->u_arg[0], "P_???");
168 tprintf(", %ld, ", tcp->u_arg[1]);
169 }
170 else {
171 /* siginfo */
172 printsiginfo_at(tcp, tcp->u_arg[2]);
173 /* options */
174 tprints(", ");
175 printflags(wait4_options, tcp->u_arg[3], "W???");
176 if (tcp->s_ent->nargs > 4) {
177 /* usage */
178 tprints(", ");
179 if (!tcp->u_arg[4])
180 tprints("NULL");
181 else if (tcp->u_error)
182 tprintf("%#lx", tcp->u_arg[4]);
183 else
184 printrusage(tcp, tcp->u_arg[4]);
185 }
186 }
187 return 0;
188}