1 /*
2 * Copyright (c) 2002-2003 Roland McGrath <roland@redhat.com>
3 * Copyright (c) 2007-2008 Ulrich Drepper <drepper@redhat.com>
4 * Copyright (c) 2009 Andreas Schwab <schwab@redhat.com>
5 * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@strace.io>
6 * Copyright (c) 2014-2022 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: LGPL-2.1-or-later
10 */
11
12 #include "defs.h"
13
14 #ifndef FUTEX_PRIVATE_FLAG
15 # define FUTEX_PRIVATE_FLAG 128
16 #endif
17 #ifndef FUTEX_CLOCK_REALTIME
18 # define FUTEX_CLOCK_REALTIME 256
19 #endif
20 #ifndef FUTEX_OP_OPARG_SHIFT
21 # define FUTEX_OP_OPARG_SHIFT 8
22 #endif
23
24 #include "xlat/futexbitset.h"
25 #include "xlat/futexops.h"
26 #include "xlat/futexwakeops.h"
27 #include "xlat/futexwakecmps.h"
28
29 static int
30 do_futex(struct tcb *const tcp, const print_obj_by_addr_fn print_ts)
31 {
32 const kernel_ulong_t uaddr = tcp->u_arg[0];
33 const int op = tcp->u_arg[1];
34 const int cmd = op & 127;
35 const kernel_ulong_t timeout = tcp->u_arg[3];
36 const kernel_ulong_t uaddr2 = tcp->u_arg[4];
37 const unsigned int val = tcp->u_arg[2];
38 const unsigned int val2 = tcp->u_arg[3];
39 const unsigned int val3 = tcp->u_arg[5];
40 const char *comment;
41
42 /* uaddr */
43 printaddr(uaddr);
44 tprint_arg_next();
45
46 /* futex_op */
47 printxval(futexops, op, "FUTEX_???");
48
49 switch (cmd) {
50 case FUTEX_WAIT:
51 tprint_arg_next();
52 PRINT_VAL_U(val);
53
54 tprint_arg_next();
55 print_ts(tcp, timeout);
56 break;
57 case FUTEX_LOCK_PI:
58 case FUTEX_LOCK_PI2:
59 tprint_arg_next();
60 print_ts(tcp, timeout);
61 break;
62 case FUTEX_WAIT_BITSET:
63 tprint_arg_next();
64 PRINT_VAL_U(val);
65
66 tprint_arg_next();
67 print_ts(tcp, timeout);
68
69 tprint_arg_next();
70 printxval(futexbitset, val3, NULL);
71 break;
72 case FUTEX_WAKE_BITSET:
73 tprint_arg_next();
74 PRINT_VAL_U(val);
75
76 tprint_arg_next();
77 printxval(futexbitset, val3, NULL);
78 break;
79 case FUTEX_REQUEUE:
80 tprint_arg_next();
81 PRINT_VAL_U(val);
82
83 tprint_arg_next();
84 PRINT_VAL_U(val2);
85
86 tprint_arg_next();
87 printaddr(uaddr2);
88 break;
89 case FUTEX_CMP_REQUEUE:
90 case FUTEX_CMP_REQUEUE_PI:
91 tprint_arg_next();
92 PRINT_VAL_U(val);
93
94 tprint_arg_next();
95 PRINT_VAL_U(val2);
96
97 tprint_arg_next();
98 printaddr(uaddr2);
99
100 tprint_arg_next();
101 PRINT_VAL_U(val3);
102 break;
103 case FUTEX_WAKE_OP:
104 tprint_arg_next();
105 PRINT_VAL_U(val);
106
107 tprint_arg_next();
108 PRINT_VAL_U(val2);
109
110 tprint_arg_next();
111 printaddr(uaddr2);
112
113 tprint_arg_next();
114 tprint_flags_begin();
115 if ((val3 >> 28) & FUTEX_OP_OPARG_SHIFT) {
116 tprint_shift_begin();
117 print_xlat(FUTEX_OP_OPARG_SHIFT);
118 tprint_shift();
119 PRINT_VAL_U(28);
120 tprint_shift_end();
121 tprint_flags_or();
122 }
123 tprint_shift_begin();
124 comment = printxval(futexwakeops, (val3 >> 28) & 0x7, NULL)
125 ? NULL : "FUTEX_OP_???";
126 tprint_shift();
127 PRINT_VAL_U(28);
128 tprint_shift_end();
129 tprints_comment(comment);
130 tprint_flags_or();
131 tprint_shift_begin();
132 PRINT_VAL_X((val3 >> 12) & 0xfff);
133 tprint_shift();
134 PRINT_VAL_U(12);
135 tprint_shift_end();
136 tprint_flags_or();
137 tprint_shift_begin();
138 comment = printxval(futexwakecmps, (val3 >> 24) & 0xf, NULL)
139 ? NULL : "FUTEX_OP_CMP_???";
140 tprint_shift();
141 PRINT_VAL_U(24);
142 tprint_shift_end();
143 tprints_comment(comment);
144 tprint_flags_or();
145 PRINT_VAL_X(val3 & 0xfff);
146 tprint_flags_end();
147 break;
148 case FUTEX_WAIT_REQUEUE_PI:
149 tprint_arg_next();
150 PRINT_VAL_U(val);
151
152 tprint_arg_next();
153 print_ts(tcp, timeout);
154
155 tprint_arg_next();
156 printaddr(uaddr2);
157 break;
158 case FUTEX_FD:
159 case FUTEX_WAKE:
160 tprint_arg_next();
161 PRINT_VAL_U(val);
162 break;
163 case FUTEX_UNLOCK_PI:
164 case FUTEX_TRYLOCK_PI:
165 break;
166 default:
167 tprint_arg_next();
168 PRINT_VAL_U(val);
169
170 tprint_arg_next();
171 printaddr(timeout);
172
173 tprint_arg_next();
174 printaddr(uaddr2);
175
176 tprint_arg_next();
177 PRINT_VAL_X(val3);
178 break;
179 }
180
181 return RVAL_DECODED;
182 }
183
184 #if HAVE_ARCH_TIME32_SYSCALLS
185 SYS_FUNC(futex_time32)
186 {
187 return do_futex(tcp, print_timespec32);
188 }
189 #endif
190
191 SYS_FUNC(futex_time64)
192 {
193 return do_futex(tcp, print_timespec64);
194 }