1 /*
2 * Copyright (c) 1993 Ulrich Pegelow <pegelow@moorea.uni-muenster.de>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 2003-2006 Roland McGrath <roland@redhat.com>
7 * Copyright (c) 2006-2015 Dmitry V. Levin <ldv@strace.io>
8 * Copyright (c) 2015-2022 The strace developers.
9 * All rights reserved.
10 *
11 * SPDX-License-Identifier: LGPL-2.1-or-later
12 */
13
14 #include "defs.h"
15 #include "ipc_defs.h"
16
17 #include SEM_H_PROVIDER
18
19 #include "xlat/semop_flags.h"
20
21 static bool
22 print_sembuf(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
23 {
24 const struct sembuf *const sb = elem_buf;
25
26 tprint_struct_begin();
27 PRINT_FIELD_U(*sb, sem_num);
28 tprint_struct_next();
29 PRINT_FIELD_D(*sb, sem_op);
30 tprint_struct_next();
31 PRINT_FIELD_FLAGS(*sb, sem_flg, semop_flags, "SEM_???");
32 tprint_struct_end();
33
34 return true;
35 }
36
37 static void
38 tprint_sembuf_array(struct tcb *const tcp, const kernel_ulong_t addr,
39 const unsigned int count)
40 {
41 /* sops */
42 struct sembuf sb;
43 print_array(tcp, addr, count, &sb, sizeof(sb),
44 tfetch_mem, print_sembuf, 0);
45 tprint_arg_next();
46
47 /* nsops */
48 PRINT_VAL_U(count);
49 }
50
51 SYS_FUNC(semop)
52 {
53 /* semid */
54 PRINT_VAL_D((int) tcp->u_arg[0]);
55 tprint_arg_next();
56
57 if (indirect_ipccall(tcp)) {
58 tprint_sembuf_array(tcp, tcp->u_arg[3], tcp->u_arg[1]);
59 } else {
60 tprint_sembuf_array(tcp, tcp->u_arg[1], tcp->u_arg[2]);
61 }
62 return RVAL_DECODED;
63 }
64
65 static int
66 do_semtimedop(struct tcb *const tcp, const print_obj_by_addr_fn print_ts)
67 {
68 /* semid */
69 PRINT_VAL_D((int) tcp->u_arg[0]);
70 tprint_arg_next();
71
72 if (indirect_ipccall(tcp)) {
73 tprint_sembuf_array(tcp, tcp->u_arg[3], tcp->u_arg[1]);
74 tprint_arg_next();
75
76 /* timeout */
77 #if defined(S390) || defined(S390X)
78 print_ts(tcp, tcp->u_arg[2]);
79 #else
80 print_ts(tcp, tcp->u_arg[4]);
81 #endif
82 } else {
83 tprint_sembuf_array(tcp, tcp->u_arg[1], tcp->u_arg[2]);
84 tprint_arg_next();
85
86 /* timeout */
87 print_ts(tcp, tcp->u_arg[3]);
88 }
89 return RVAL_DECODED;
90 }
91
92 #if HAVE_ARCH_TIME32_SYSCALLS
93 SYS_FUNC(semtimedop_time32)
94 {
95 return do_semtimedop(tcp, print_timespec32);
96 }
97 #endif
98
99 SYS_FUNC(semtimedop_time64)
100 {
101 return do_semtimedop(tcp, print_timespec64);
102 }
103
104 SYS_FUNC(semget)
105 {
106 /* key */
107 printxval(ipc_private, (unsigned int) tcp->u_arg[0], NULL);
108 tprint_arg_next();
109
110 /* nsems */
111 PRINT_VAL_D((int) tcp->u_arg[1]);
112 tprint_arg_next();
113
114 /* semflg */
115 tprint_flags_begin();
116 if (printflags_in(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
117 tprint_flags_or();
118 print_numeric_umode_t(tcp->u_arg[2] & 0777);
119 tprint_flags_end();
120 return RVAL_DECODED;
121 }