blob: 2e495dbf94117a5acf861a28eecff4a5a7b8c35b [file] [log] [blame]
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +00001#include "defs.h"
2
3#include <sys/wait.h>
4
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +00005#include "xlat/wait4_options.h"
6
7#if !defined WCOREFLAG && defined WCOREFLG
8# define WCOREFLAG WCOREFLG
9#endif
10#ifndef WCOREFLAG
11# define WCOREFLAG 0x80
12#endif
13#ifndef WCOREDUMP
14# define WCOREDUMP(status) ((status) & 0200)
15#endif
16#ifndef W_STOPCODE
17# define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
18#endif
19#ifndef W_EXITCODE
20# define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
21#endif
Dmitry V. Levind8b34042015-02-12 22:43:02 +000022#ifndef W_CONTINUED
23# define W_CONTINUED 0xffff
24#endif
25
Dmitry V. Levinfadf3792015-02-13 00:26:38 +000026#include "ptrace.h"
Dmitry V. Levind8b34042015-02-12 22:43:02 +000027#include "xlat/ptrace_events.h"
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000028
29static int
30printstatus(int status)
31{
32 int exited = 0;
33
34 /*
35 * Here is a tricky presentation problem. This solution
36 * is still not entirely satisfactory but since there
37 * are no wait status constructors it will have to do.
38 */
39 if (WIFSTOPPED(status)) {
Dmitry V. Levind8b34042015-02-12 22:43:02 +000040 int sig = WSTOPSIG(status);
41 tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s%s}",
42 signame(sig & 0x7f),
43 sig & 0x80 ? " | 0x80" : "");
44 status &= ~W_STOPCODE(sig);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000045 }
46 else if (WIFSIGNALED(status)) {
47 tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
48 signame(WTERMSIG(status)),
49 WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
50 status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
51 }
52 else if (WIFEXITED(status)) {
53 tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
54 WEXITSTATUS(status));
55 exited = 1;
56 status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
57 }
Dmitry V. Levind8b34042015-02-12 22:43:02 +000058#ifdef WIFCONTINUED
59 else if (WIFCONTINUED(status)) {
60 tprints("[{WIFCONTINUED(s)}");
61 status &= ~W_CONTINUED;
62 }
63#endif
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000064 else {
65 tprintf("[%#x]", status);
66 return 0;
67 }
68
Dmitry V. Levind8b34042015-02-12 22:43:02 +000069 if (status) {
70 unsigned int event = (unsigned int) status >> 16;
71 if (event) {
72 tprints(" | ");
73 printxval(ptrace_events, event, "PTRACE_EVENT_???");
74 tprints(" << 16");
75 status &= 0xffff;
76 }
77 if (status)
78 tprintf(" | %#x", status);
79 }
80 tprints("]");
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +000081
82 return exited;
83}
84
85static int
86printwaitn(struct tcb *tcp, int n, int bitness)
87{
88 int status;
89
90 if (entering(tcp)) {
91 /* On Linux, kernel-side pid_t is typedef'ed to int
92 * on all arches. Also, glibc-2.8 truncates wait3 and wait4
93 * pid argument to int on 64bit arches, producing,
94 * for example, wait4(4294967295, ...) instead of -1
95 * in strace. We have to use int here, not long.
96 */
97 int pid = tcp->u_arg[0];
98 tprintf("%d, ", pid);
99 } else {
100 /* status */
Dmitry V. Levin90cfe8f2015-07-15 00:36:20 +0000101 if (tcp->u_rval == 0)
102 printaddr(tcp->u_arg[1]);
103 else if (!umove_or_printaddr(tcp, tcp->u_arg[1], &status))
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000104 printstatus(status);
105 /* options */
106 tprints(", ");
107 printflags(wait4_options, tcp->u_arg[2], "W???");
108 if (n == 4) {
109 tprints(", ");
110 /* usage */
Dmitry V. Levin90cfe8f2015-07-15 00:36:20 +0000111 if (tcp->u_rval > 0) {
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000112#ifdef ALPHA
113 if (bitness)
114 printrusage32(tcp, tcp->u_arg[3]);
115 else
116#endif
Dmitry V. Levine2fb0bb2015-09-15 21:51:15 +0000117 printrusage(tcp, tcp->u_arg[3]);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000118 }
119 else
Dmitry V. Levin90cfe8f2015-07-15 00:36:20 +0000120 printaddr(tcp->u_arg[3]);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000121 }
122 }
123 return 0;
124}
125
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000126SYS_FUNC(waitpid)
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000127{
128 return printwaitn(tcp, 3, 0);
129}
130
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000131SYS_FUNC(wait4)
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000132{
133 return printwaitn(tcp, 4, 0);
134}
135
136#ifdef ALPHA
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000137SYS_FUNC(osf_wait4)
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000138{
139 return printwaitn(tcp, 4, 1);
140}
141#endif
142
143#include "xlat/waitid_types.h"
144
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000145SYS_FUNC(waitid)
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000146{
147 if (entering(tcp)) {
148 printxval(waitid_types, tcp->u_arg[0], "P_???");
149 tprintf(", %ld, ", tcp->u_arg[1]);
Dmitry V. Levin90cfe8f2015-07-15 00:36:20 +0000150 } else {
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000151 /* siginfo */
Dmitry V. Levine2fb0bb2015-09-15 21:51:15 +0000152 printsiginfo_at(tcp, tcp->u_arg[2]);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000153 /* options */
154 tprints(", ");
155 printflags(wait4_options, tcp->u_arg[3], "W???");
156 if (tcp->s_ent->nargs > 4) {
157 /* usage */
158 tprints(", ");
Dmitry V. Levine2fb0bb2015-09-15 21:51:15 +0000159 printrusage(tcp, tcp->u_arg[4]);
Dmitry V. Levin7ccc1442014-12-11 19:25:02 +0000160 }
161 }
162 return 0;
163}