]> granicus.if.org Git - strace/blob - time.c
2004-08-31 Roland McGrath <roland@redhat.com>
[strace] / time.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #ifdef LINUX
35 #include <linux/version.h>
36 #include <sys/timex.h>
37 #endif /* LINUX */
38
39 void
40 printtv(tcp, addr)
41 struct tcb *tcp;
42 long addr;
43 {
44         struct timeval tv;
45
46         if (addr == 0)
47                 tprintf("NULL");
48         else if (!verbose(tcp))
49                 tprintf("%#lx", addr);
50         else if (umove(tcp, addr, &tv) < 0)
51                 tprintf("{...}");
52         else
53                 tprintf("{%lu, %lu}", (long) tv.tv_sec, (long) tv.tv_usec);
54 }
55
56 #ifdef ALPHA
57 struct timeval32
58 {
59     unsigned tv_sec;
60     unsigned tv_usec;
61 };
62
63 void
64 printtv32(tcp, addr)
65 struct tcb *tcp;
66 long addr;
67 {
68     struct timeval32  tv;
69
70     if (addr == 0)
71         tprintf("NULL");
72     else if (!verbose(tcp))
73         tprintf("%#lx", addr);
74     else if (umove(tcp, addr, &tv) < 0)
75         tprintf("{...}");
76     else
77         tprintf("{%u, %u}", tv.tv_sec, tv.tv_usec);
78 }
79 #endif
80
81
82 int
83 sys_time(tcp)
84 struct tcb *tcp;
85 {
86         if (exiting(tcp)) {
87 #ifndef SVR4
88                 printnum(tcp, tcp->u_arg[0], "%ld");
89 #endif /* SVR4 */
90         }
91         return 0;
92 }
93
94 int
95 sys_stime(tcp)
96 struct tcb *tcp;
97 {
98         if (exiting(tcp)) {
99                 printnum(tcp, tcp->u_arg[0], "%ld");
100         }
101         return 0;
102 }
103
104 int
105 sys_gettimeofday(tcp)
106 struct tcb *tcp;
107 {
108         if (exiting(tcp)) {
109                 if (syserror(tcp)) {
110                         tprintf("%#lx, %#lx",
111                                 tcp->u_arg[0], tcp->u_arg[1]);
112                         return 0;
113                 }
114                 printtv(tcp, tcp->u_arg[0]);
115 #ifndef SVR4
116                 tprintf(", ");
117                 printtv(tcp, tcp->u_arg[1]);
118 #endif /* !SVR4 */
119         }
120         return 0;
121 }
122
123
124 #ifdef ALPHA
125 int
126 sys_osf_gettimeofday(tcp)
127 struct tcb *tcp;
128 {
129     if (exiting(tcp)) {
130         if (syserror(tcp)) {
131             tprintf("%#lx, %#lx",
132                     tcp->u_arg[0], tcp->u_arg[1]);
133             return 0;
134         }
135         printtv32(tcp, tcp->u_arg[0]);
136 #ifndef SVR4
137         tprintf(", ");
138         printtv32(tcp, tcp->u_arg[1]);
139 #endif /* !SVR4 */
140     }
141     return 0;
142 }
143 #endif
144
145 int
146 sys_settimeofday(tcp)
147 struct tcb *tcp;
148 {
149         if (entering(tcp)) {
150                 printtv(tcp, tcp->u_arg[0]);
151 #ifndef SVR4
152                 tprintf(", ");
153                 printtv(tcp, tcp->u_arg[1]);
154 #endif /* !SVR4 */
155         }
156         return 0;
157 }
158
159 #ifdef ALPHA
160 int
161 sys_osf_settimeofday(tcp)
162 struct tcb *tcp;
163 {
164     if (entering(tcp)) {
165         printtv32(tcp, tcp->u_arg[0]);
166 #ifndef SVR4
167         tprintf(", ");
168         printtv32(tcp, tcp->u_arg[1]);
169 #endif /* !SVR4 */
170     }
171     return 0;
172 }
173 #endif
174
175 int
176 sys_adjtime(tcp)
177 struct tcb *tcp;
178 {
179         if (entering(tcp)) {
180                 printtv(tcp, tcp->u_arg[0]);
181                 tprintf(", ");
182         } else {
183                 if (syserror(tcp))
184                         tprintf("%#lx", tcp->u_arg[1]);
185                 else
186                         printtv(tcp, tcp->u_arg[1]);
187         }
188         return 0;
189 }
190
191 static struct xlat which[] = {
192         { ITIMER_REAL,  "ITIMER_REAL"   },
193         { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
194         { ITIMER_PROF,  "ITIMER_PROF"   },
195         { 0,            NULL            },
196 };
197
198 static void
199 printitv(tcp, addr)
200 struct tcb *tcp;
201 long addr;
202 {
203         struct itimerval itv;
204
205         if (addr == 0)
206                 tprintf("NULL");
207         else if (!verbose(tcp))
208                 tprintf("%#lx", addr);
209         else if (umove(tcp, addr, &itv) < 0)
210                 tprintf("{...}");
211         else {
212                 tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}",
213                 (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec,
214                 (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec);
215         }
216 }
217
218
219 #ifdef ALPHA
220 static void
221 printitv32(tcp, addr)
222 struct tcb *tcp;
223 long addr;
224 {
225     struct itimerval32
226     {
227         struct timeval32 it_interval;
228         struct timeval32 it_value;
229     } itv;
230
231     if (addr == 0)
232         tprintf("NULL");
233     else if (!verbose(tcp))
234         tprintf("%#lx", addr);
235     else if (umove(tcp, addr, &itv) < 0)
236         tprintf("{...}");
237     else {
238         tprintf("{it_interval={%u, %u}, it_value={%u, %u}}",
239                 itv.it_interval.tv_sec, itv.it_interval.tv_usec,
240                 itv.it_value.tv_sec, itv.it_value.tv_usec);
241     }
242 }
243 #endif
244
245 int
246 sys_getitimer(tcp)
247 struct tcb *tcp;
248 {
249         if (entering(tcp)) {
250                 printxval(which, tcp->u_arg[0], "ITIMER_???");
251                 tprintf(", ");
252         } else {
253                 if (syserror(tcp))
254                         tprintf("%#lx", tcp->u_arg[1]);
255                 else
256                         printitv(tcp, tcp->u_arg[1]);
257         }
258         return 0;
259 }
260
261
262 #ifdef ALPHA
263 int
264 sys_osf_getitimer(tcp)
265 struct tcb *tcp;
266 {
267     if (entering(tcp)) {
268         printxval(which, tcp->u_arg[0], "ITIMER_???");
269         tprintf(", ");
270     } else {
271         if (syserror(tcp))
272             tprintf("%#lx", tcp->u_arg[1]);
273         else
274             printitv32(tcp, tcp->u_arg[1]);
275     }
276     return 0;
277 }
278 #endif
279
280 int
281 sys_setitimer(tcp)
282 struct tcb *tcp;
283 {
284         if (entering(tcp)) {
285                 printxval(which, tcp->u_arg[0], "ITIMER_???");
286                 tprintf(", ");
287                 printitv(tcp, tcp->u_arg[1]);
288                 tprintf(", ");
289         } else {
290                 if (syserror(tcp))
291                         tprintf("%#lx", tcp->u_arg[2]);
292                 else
293                         printitv(tcp, tcp->u_arg[2]);
294         }
295         return 0;
296 }
297
298 #ifdef ALPHA
299 int
300 sys_osf_setitimer(tcp)
301 struct tcb *tcp;
302 {
303     if (entering(tcp)) {
304         printxval(which, tcp->u_arg[0], "ITIMER_???");
305         tprintf(", ");
306         printitv32(tcp, tcp->u_arg[1]);
307         tprintf(", ");
308     } else {
309         if (syserror(tcp))
310             tprintf("%#lx", tcp->u_arg[2]);
311         else
312             printitv32(tcp, tcp->u_arg[2]);
313     }
314     return 0;
315 }
316 #endif
317
318 #ifdef LINUX
319
320 int
321 sys_adjtimex(tcp)
322 struct tcb *tcp;
323 {
324         struct timex txc;
325
326         if (exiting(tcp)) {
327                 if (tcp->u_arg[0] == 0)
328                         tprintf("NULL");
329                 else if (syserror(tcp) || !verbose(tcp))
330                         tprintf("%#lx", tcp->u_arg[0]);
331                 else if (umove(tcp, tcp->u_arg[0], &txc) < 0)
332                         tprintf("{...}");
333                 else {
334 #if LINUX_VERSION_CODE < 66332
335                         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
336                                 txc.mode, txc.offset, txc.frequency);
337                         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
338                                 txc.maxerror, txc.esterror, txc.status);
339                         tprintf("time_constant=%ld, precision=%lu, ",
340                                 txc.time_constant, txc.precision);
341                         tprintf("tolerance=%ld, time={%lu, %lu}}",
342                                 txc.tolerance, (long) txc.time.tv_sec,
343                                 (long) txc.time.tv_usec);
344 #else
345                         tprintf("{modes=%d, offset=%ld, freq=%ld, ",
346                                 txc.modes, txc.offset, txc.freq);
347                         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
348                                 txc.maxerror, txc.esterror, txc.status);
349                         tprintf("constant=%ld, precision=%lu, ",
350                                 txc.constant, txc.precision);
351                         tprintf("tolerance=%ld, time={%lu, %lu}}",
352                                 txc.tolerance, (long) txc.time.tv_sec,
353                                 (long) txc.time.tv_usec);
354                         /* there's a bunch of other stuff, but it's not
355                          * worth the time or the trouble to include */
356 #endif
357                 }
358         }
359         return 0;
360 }
361
362 static struct xlat clockflags[] = {
363   { TIMER_ABSTIME, "TIMER_ABSTIME" },
364   { 0,             NULL }
365 };
366
367 static struct xlat clocknames[] = {
368 #ifdef CLOCK_REALTIME
369   { CLOCK_REALTIME, "CLOCK_REALTIME" },
370 #endif
371 #ifdef CLOCK_MONOTONIC
372   { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
373 #endif
374   { 0,             NULL }
375 };
376
377 int
378 sys_clock_settime(tcp)
379 struct tcb *tcp;
380 {
381         if (entering(tcp)) {
382                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
383                 tprintf(", ");
384                 printtv(tcp, tcp->u_arg[1]);
385         }
386         return 0;
387 }
388
389 int
390 sys_clock_gettime(tcp)
391 struct tcb *tcp;
392 {
393         if (entering(tcp)) {
394                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
395                 tprintf(", ");
396         } else {
397                 if (syserror(tcp))
398                         tprintf("%#lx", tcp->u_arg[1]);
399                 else
400                         printtv(tcp, tcp->u_arg[1]);
401         }
402         return 0;
403 }
404
405 int
406 sys_clock_nanosleep(tcp)
407 struct tcb *tcp;
408 {
409         if (entering(tcp)) {
410                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
411                 tprintf(", ");
412                 printflags(clockflags, tcp->u_arg[1]);
413                 tprintf(", ");
414                 printtv(tcp, tcp->u_arg[2]);
415                 tprintf(", ");
416         } else {
417                 if (syserror(tcp))
418                         tprintf("%#lx", tcp->u_arg[3]);
419                 else
420                         printtv(tcp, tcp->u_arg[3]);
421         }
422         return 0;
423 }
424
425 #ifndef SIGEV_THREAD_ID
426 # define SIGEV_THREAD_ID 4
427 #endif
428 static struct xlat sigev_value[] = {
429         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
430         { SIGEV_NONE+1, "SIGEV_NONE" },
431         { SIGEV_THREAD+1, "SIGEV_THREAD" },
432         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
433         { 0, NULL }
434 };
435
436 void
437 printsigevent(tcp, arg)
438 struct tcb *tcp;
439 long arg;
440 {
441         struct sigevent sev;
442         if (umove (tcp, arg, &sev) < 0)
443                 tprintf("{...}");
444         else {
445                 tprintf("{%p, %u, ", sev.sigev_value.sival_ptr,
446                         sev.sigev_signo);
447                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
448                 tprintf(", ");
449                 if (sev.sigev_notify == SIGEV_THREAD_ID)
450                         /* _pad[0] is the _tid field which might not be
451                            present in the userlevel definition of the
452                            struct.  */
453                         tprintf("{%d}", sev._sigev_un._pad[0]);
454                 else if (sev.sigev_notify == SIGEV_THREAD)
455                         tprintf("{%p, %p}", sev.sigev_notify_function,
456                                 sev.sigev_notify_attributes);
457                 else
458                         tprintf("{...}");
459                 tprintf("}");
460         }
461 }
462
463 int
464 sys_timer_create(tcp)
465 struct tcb *tcp;
466 {
467         if (entering(tcp)) {
468                 tprintf("%#lx, ", tcp->u_arg[0]);
469                 printsigevent(tcp, tcp->u_arg[1]);
470                 tprintf(", ");
471         } else {
472                 if (syserror(tcp))
473                         tprintf("%#lx", tcp->u_arg[2]);
474                 else {
475                         void *p;
476                         umove(tcp, tcp->u_arg[2], &p);
477                         tprintf("{%p}", p);
478                 }
479         }
480         return 0;
481 }
482
483 int
484 sys_timer_settime(tcp)
485 struct tcb *tcp;
486 {
487         if (entering(tcp)) {
488                 tprintf("%#lx, ", tcp->u_arg[0]);
489                 printflags(clockflags, tcp->u_arg[1]);
490                 tprintf(", ");
491                 printitv(tcp, tcp->u_arg[2]);
492                 tprintf(", ");
493         } else {
494                 if (syserror(tcp))
495                         tprintf("%#lx", tcp->u_arg[3]);
496                 else
497                         printitv(tcp, tcp->u_arg[3]);
498         }
499         return 0;
500 }
501
502 int
503 sys_timer_gettime(tcp)
504 struct tcb *tcp;
505 {
506         if (entering(tcp)) {
507                 tprintf("%#lx, ", tcp->u_arg[0]);
508         } else {
509                 if (syserror(tcp))
510                         tprintf("%#lx", tcp->u_arg[1]);
511                 else
512                         printitv(tcp, tcp->u_arg[1]);
513         }
514         return 0;
515 }
516 #endif /* LINUX */