1 /*
2 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@strace.io>
3 * Copyright (c) 2016-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #include "defs.h"
10
11 #include DEF_MPERS_TYPE(timeval_t)
12
13 #include "kernel_timeval.h"
14
15 typedef kernel_old_timeval_t timeval_t;
16
17 #include MPERS_DEFS
18
19 #include "xstring.h"
20
21 static const char timeval_fmt[] = "{tv_sec=%lld, tv_usec=%llu}";
22
23 static void
24 print_timeval_t(const timeval_t *t)
25 {
26 tprint_struct_begin();
27 PRINT_FIELD_D(*t, tv_sec);
28 tprint_struct_next();
29 PRINT_FIELD_U(*t, tv_usec);
30 tprint_struct_end();
31 }
32
33 static bool
34 print_timeval_t_utime(struct tcb *tcp, void *elem_buf, size_t elem_size,
35 void *data)
36 {
37 const timeval_t *const t = elem_buf;
38 print_timeval_t(t);
39 tprints_comment(sprinttime_usec(t->tv_sec,
40 zero_extend_signed_to_ull(t->tv_usec)));
41 return true;
42 }
43
44 MPERS_PRINTER_DECL(void, print_struct_timeval, const void *arg)
45 {
46 print_timeval_t(arg);
47 }
48
49 MPERS_PRINTER_DECL(bool, print_struct_timeval_data_size,
50 const void *arg, const size_t size)
51 {
52 if (size < sizeof(timeval_t)) {
53 tprint_unavailable();
54 return false;
55 }
56
57 print_timeval_t(arg);
58 return true;
59 }
60
61 MPERS_PRINTER_DECL(int, print_timeval,
62 struct tcb *const tcp, const kernel_ulong_t addr)
63 {
64 timeval_t t;
65
66 if (umove_or_printaddr(tcp, addr, &t))
67 return -1;
68
69 print_timeval_t(&t);
70 return 0;
71 }
72
73 MPERS_PRINTER_DECL(int, print_timeval_utimes,
74 struct tcb *const tcp, const kernel_ulong_t addr)
75 {
76 timeval_t t[2];
77
78 if (umove_or_printaddr(tcp, addr, &t))
79 return -1;
80
81 print_local_array(tcp, t, print_timeval_t_utime);
82 return 0;
83 }
84
85 MPERS_PRINTER_DECL(const char *, sprint_timeval,
86 struct tcb *const tcp, const kernel_ulong_t addr)
87 {
88 timeval_t t;
89 static char buf[sizeof(timeval_fmt) + 3 * sizeof(t)];
90
91 if (!addr) {
92 strcpy(buf, "NULL");
93 } else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
94 umove(tcp, addr, &t)) {
95 xsprintf(buf, "%#" PRI_klx, addr);
96 } else {
97 xsprintf(buf, timeval_fmt,
98 (long long) t.tv_sec,
99 zero_extend_signed_to_ull(t.tv_usec));
100 }
101
102 return buf;
103 }
104
105 MPERS_PRINTER_DECL(int, print_itimerval,
106 struct tcb *const tcp, const kernel_ulong_t addr)
107 {
108 struct { timeval_t it_interval, it_value; } t;
109
110 if (umove_or_printaddr(tcp, addr, &t))
111 return -1;
112
113 tprint_struct_begin();
114 PRINT_FIELD_OBJ_PTR(t, it_interval, print_timeval_t);
115 tprint_struct_next();
116 PRINT_FIELD_OBJ_PTR(t, it_value, print_timeval_t);
117 tprint_struct_end();
118 return 0;
119 }
120
121 #ifdef ALPHA
122
123 void
124 print_timeval32_t(const timeval32_t *t)
125 {
126 tprint_struct_begin();
127 PRINT_FIELD_D(*t, tv_sec);
128 tprint_struct_next();
129 PRINT_FIELD_U(*t, tv_usec);
130 tprint_struct_end();
131 }
132
133 static bool
134 print_timeval32_t_utime(struct tcb *tcp, void *elem_buf, size_t elem_size,
135 void *data)
136 {
137 const timeval32_t *const t = elem_buf;
138 print_timeval32_t(t);
139 tprints_comment(sprinttime_usec(t->tv_sec,
140 zero_extend_signed_to_ull(t->tv_usec)));
141 return true;
142 }
143
144 int
145 print_timeval32(struct tcb *const tcp, const kernel_ulong_t addr)
146 {
147 timeval32_t t;
148
149 if (umove_or_printaddr(tcp, addr, &t))
150 return -1;
151
152 print_timeval32_t(&t);
153 return 0;
154 }
155
156 int
157 print_timeval32_utimes(struct tcb *const tcp, const kernel_ulong_t addr)
158 {
159 timeval32_t t[2];
160
161 if (umove_or_printaddr(tcp, addr, &t))
162 return -1;
163
164 print_local_array(tcp, t, print_timeval32_t_utime);
165 return 0;
166 }
167
168 int
169 print_itimerval32(struct tcb *const tcp, const kernel_ulong_t addr)
170 {
171 struct { timeval32_t it_interval, it_value; } t;
172
173 if (umove_or_printaddr(tcp, addr, &t))
174 return -1;
175
176 tprint_struct_begin();
177 PRINT_FIELD_OBJ_PTR(t, it_interval, print_timeval32_t);
178 tprint_struct_next();
179 PRINT_FIELD_OBJ_PTR(t, it_value, print_timeval32_t);
180 tprint_struct_end();
181 return 0;
182 }
183
184 const char *
185 sprint_timeval32(struct tcb *const tcp, const kernel_ulong_t addr)
186 {
187 timeval32_t t;
188 static char buf[sizeof(timeval_fmt) + 3 * sizeof(t)];
189
190 if (!addr) {
191 strcpy(buf, "NULL");
192 } else if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) ||
193 umove(tcp, addr, &t)) {
194 xsprintf(buf, "%#" PRI_klx, addr);
195 } else {
196 xsprintf(buf, timeval_fmt,
197 (long long) t.tv_sec,
198 zero_extend_signed_to_ull(t.tv_usec));
199 }
200
201 return buf;
202 }
203
204 #endif /* ALPHA */