]> granicus.if.org Git - strace/blob - time.c
2005-06-08 Dmitry V. Levin <ldv@altlinux.org>
[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 #include <linux/ioctl.h>
38 #include <linux/rtc.h>
39 #endif /* LINUX */
40
41 void
42 printtv(tcp, addr)
43 struct tcb *tcp;
44 long addr;
45 {
46         struct timeval tv;
47
48         if (addr == 0)
49                 tprintf("NULL");
50         else if (!verbose(tcp))
51                 tprintf("%#lx", addr);
52         else if (umove(tcp, addr, &tv) < 0)
53                 tprintf("{...}");
54         else
55                 tprintf("{%lu, %lu}", (long) tv.tv_sec, (long) tv.tv_usec);
56 }
57
58 #ifdef ALPHA
59 struct timeval32
60 {
61     unsigned tv_sec;
62     unsigned tv_usec;
63 };
64
65 void
66 printtv32(tcp, addr)
67 struct tcb *tcp;
68 long addr;
69 {
70     struct timeval32  tv;
71
72     if (addr == 0)
73         tprintf("NULL");
74     else if (!verbose(tcp))
75         tprintf("%#lx", addr);
76     else if (umove(tcp, addr, &tv) < 0)
77         tprintf("{...}");
78     else
79         tprintf("{%u, %u}", tv.tv_sec, tv.tv_usec);
80 }
81 #endif
82
83
84 int
85 sys_time(tcp)
86 struct tcb *tcp;
87 {
88         if (exiting(tcp)) {
89 #ifndef SVR4
90                 printnum(tcp, tcp->u_arg[0], "%ld");
91 #endif /* SVR4 */
92         }
93         return 0;
94 }
95
96 int
97 sys_stime(tcp)
98 struct tcb *tcp;
99 {
100         if (exiting(tcp)) {
101                 printnum(tcp, tcp->u_arg[0], "%ld");
102         }
103         return 0;
104 }
105
106 int
107 sys_gettimeofday(tcp)
108 struct tcb *tcp;
109 {
110         if (exiting(tcp)) {
111                 if (syserror(tcp)) {
112                         tprintf("%#lx, %#lx",
113                                 tcp->u_arg[0], tcp->u_arg[1]);
114                         return 0;
115                 }
116                 printtv(tcp, tcp->u_arg[0]);
117 #ifndef SVR4
118                 tprintf(", ");
119                 printtv(tcp, tcp->u_arg[1]);
120 #endif /* !SVR4 */
121         }
122         return 0;
123 }
124
125
126 #ifdef ALPHA
127 int
128 sys_osf_gettimeofday(tcp)
129 struct tcb *tcp;
130 {
131     if (exiting(tcp)) {
132         if (syserror(tcp)) {
133             tprintf("%#lx, %#lx",
134                     tcp->u_arg[0], tcp->u_arg[1]);
135             return 0;
136         }
137         printtv32(tcp, tcp->u_arg[0]);
138 #ifndef SVR4
139         tprintf(", ");
140         printtv32(tcp, tcp->u_arg[1]);
141 #endif /* !SVR4 */
142     }
143     return 0;
144 }
145 #endif
146
147 int
148 sys_settimeofday(tcp)
149 struct tcb *tcp;
150 {
151         if (entering(tcp)) {
152                 printtv(tcp, tcp->u_arg[0]);
153 #ifndef SVR4
154                 tprintf(", ");
155                 printtv(tcp, tcp->u_arg[1]);
156 #endif /* !SVR4 */
157         }
158         return 0;
159 }
160
161 #ifdef ALPHA
162 int
163 sys_osf_settimeofday(tcp)
164 struct tcb *tcp;
165 {
166     if (entering(tcp)) {
167         printtv32(tcp, tcp->u_arg[0]);
168 #ifndef SVR4
169         tprintf(", ");
170         printtv32(tcp, tcp->u_arg[1]);
171 #endif /* !SVR4 */
172     }
173     return 0;
174 }
175 #endif
176
177 int
178 sys_adjtime(tcp)
179 struct tcb *tcp;
180 {
181         if (entering(tcp)) {
182                 printtv(tcp, tcp->u_arg[0]);
183                 tprintf(", ");
184         } else {
185                 if (syserror(tcp))
186                         tprintf("%#lx", tcp->u_arg[1]);
187                 else
188                         printtv(tcp, tcp->u_arg[1]);
189         }
190         return 0;
191 }
192
193 static const struct xlat which[] = {
194         { ITIMER_REAL,  "ITIMER_REAL"   },
195         { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
196         { ITIMER_PROF,  "ITIMER_PROF"   },
197         { 0,            NULL            },
198 };
199
200 static void
201 printitv(tcp, addr)
202 struct tcb *tcp;
203 long addr;
204 {
205         struct itimerval itv;
206
207         if (addr == 0)
208                 tprintf("NULL");
209         else if (!verbose(tcp))
210                 tprintf("%#lx", addr);
211         else if (umove(tcp, addr, &itv) < 0)
212                 tprintf("{...}");
213         else {
214                 tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}",
215                 (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec,
216                 (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec);
217         }
218 }
219
220
221 #ifdef ALPHA
222 static void
223 printitv32(tcp, addr)
224 struct tcb *tcp;
225 long addr;
226 {
227     struct itimerval32
228     {
229         struct timeval32 it_interval;
230         struct timeval32 it_value;
231     } itv;
232
233     if (addr == 0)
234         tprintf("NULL");
235     else if (!verbose(tcp))
236         tprintf("%#lx", addr);
237     else if (umove(tcp, addr, &itv) < 0)
238         tprintf("{...}");
239     else {
240         tprintf("{it_interval={%u, %u}, it_value={%u, %u}}",
241                 itv.it_interval.tv_sec, itv.it_interval.tv_usec,
242                 itv.it_value.tv_sec, itv.it_value.tv_usec);
243     }
244 }
245 #endif
246
247 int
248 sys_getitimer(tcp)
249 struct tcb *tcp;
250 {
251         if (entering(tcp)) {
252                 printxval(which, tcp->u_arg[0], "ITIMER_???");
253                 tprintf(", ");
254         } else {
255                 if (syserror(tcp))
256                         tprintf("%#lx", tcp->u_arg[1]);
257                 else
258                         printitv(tcp, tcp->u_arg[1]);
259         }
260         return 0;
261 }
262
263
264 #ifdef ALPHA
265 int
266 sys_osf_getitimer(tcp)
267 struct tcb *tcp;
268 {
269     if (entering(tcp)) {
270         printxval(which, tcp->u_arg[0], "ITIMER_???");
271         tprintf(", ");
272     } else {
273         if (syserror(tcp))
274             tprintf("%#lx", tcp->u_arg[1]);
275         else
276             printitv32(tcp, tcp->u_arg[1]);
277     }
278     return 0;
279 }
280 #endif
281
282 int
283 sys_setitimer(tcp)
284 struct tcb *tcp;
285 {
286         if (entering(tcp)) {
287                 printxval(which, tcp->u_arg[0], "ITIMER_???");
288                 tprintf(", ");
289                 printitv(tcp, tcp->u_arg[1]);
290                 tprintf(", ");
291         } else {
292                 if (syserror(tcp))
293                         tprintf("%#lx", tcp->u_arg[2]);
294                 else
295                         printitv(tcp, tcp->u_arg[2]);
296         }
297         return 0;
298 }
299
300 #ifdef ALPHA
301 int
302 sys_osf_setitimer(tcp)
303 struct tcb *tcp;
304 {
305     if (entering(tcp)) {
306         printxval(which, tcp->u_arg[0], "ITIMER_???");
307         tprintf(", ");
308         printitv32(tcp, tcp->u_arg[1]);
309         tprintf(", ");
310     } else {
311         if (syserror(tcp))
312             tprintf("%#lx", tcp->u_arg[2]);
313         else
314             printitv32(tcp, tcp->u_arg[2]);
315     }
316     return 0;
317 }
318 #endif
319
320 #ifdef LINUX
321
322 int
323 sys_adjtimex(tcp)
324 struct tcb *tcp;
325 {
326         struct timex txc;
327
328         if (exiting(tcp)) {
329                 if (tcp->u_arg[0] == 0)
330                         tprintf("NULL");
331                 else if (syserror(tcp) || !verbose(tcp))
332                         tprintf("%#lx", tcp->u_arg[0]);
333                 else if (umove(tcp, tcp->u_arg[0], &txc) < 0)
334                         tprintf("{...}");
335                 else {
336 #if LINUX_VERSION_CODE < 66332
337                         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
338                                 txc.mode, txc.offset, txc.frequency);
339                         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
340                                 txc.maxerror, txc.esterror, txc.status);
341                         tprintf("time_constant=%ld, precision=%lu, ",
342                                 txc.time_constant, txc.precision);
343                         tprintf("tolerance=%ld, time={%lu, %lu}}",
344                                 txc.tolerance, (long) txc.time.tv_sec,
345                                 (long) txc.time.tv_usec);
346 #else
347                         tprintf("{modes=%d, offset=%ld, freq=%ld, ",
348                                 txc.modes, txc.offset, txc.freq);
349                         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
350                                 txc.maxerror, txc.esterror, txc.status);
351                         tprintf("constant=%ld, precision=%lu, ",
352                                 txc.constant, txc.precision);
353                         tprintf("tolerance=%ld, time={%lu, %lu}}",
354                                 txc.tolerance, (long) txc.time.tv_sec,
355                                 (long) txc.time.tv_usec);
356                         /* there's a bunch of other stuff, but it's not
357                          * worth the time or the trouble to include */
358 #endif
359                 }
360         }
361         return 0;
362 }
363
364 static const struct xlat clockflags[] = {
365   { TIMER_ABSTIME, "TIMER_ABSTIME" },
366   { 0,             NULL }
367 };
368
369 static const struct xlat clocknames[] = {
370 #ifdef CLOCK_REALTIME
371   { CLOCK_REALTIME, "CLOCK_REALTIME" },
372 #endif
373 #ifdef CLOCK_MONOTONIC
374   { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
375 #endif
376   { 0,             NULL }
377 };
378
379 int
380 sys_clock_settime(tcp)
381 struct tcb *tcp;
382 {
383         if (entering(tcp)) {
384                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
385                 tprintf(", ");
386                 printtv(tcp, tcp->u_arg[1]);
387         }
388         return 0;
389 }
390
391 int
392 sys_clock_gettime(tcp)
393 struct tcb *tcp;
394 {
395         if (entering(tcp)) {
396                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
397                 tprintf(", ");
398         } else {
399                 if (syserror(tcp))
400                         tprintf("%#lx", tcp->u_arg[1]);
401                 else
402                         printtv(tcp, tcp->u_arg[1]);
403         }
404         return 0;
405 }
406
407 int
408 sys_clock_nanosleep(tcp)
409 struct tcb *tcp;
410 {
411         if (entering(tcp)) {
412                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
413                 tprintf(", ");
414                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
415                 tprintf(", ");
416                 printtv(tcp, tcp->u_arg[2]);
417                 tprintf(", ");
418         } else {
419                 if (syserror(tcp))
420                         tprintf("%#lx", tcp->u_arg[3]);
421                 else
422                         printtv(tcp, tcp->u_arg[3]);
423         }
424         return 0;
425 }
426
427 #ifndef SIGEV_THREAD_ID
428 # define SIGEV_THREAD_ID 4
429 #endif
430 static const struct xlat sigev_value[] = {
431         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
432         { SIGEV_NONE+1, "SIGEV_NONE" },
433         { SIGEV_THREAD+1, "SIGEV_THREAD" },
434         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
435         { 0, NULL }
436 };
437
438 void
439 printsigevent(tcp, arg)
440 struct tcb *tcp;
441 long arg;
442 {
443         struct sigevent sev;
444         if (umove (tcp, arg, &sev) < 0)
445                 tprintf("{...}");
446         else {
447                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
448                 if (sev.sigev_notify == SIGEV_SIGNAL)
449                         tprintf("%s, ", signame(sev.sigev_signo));
450                 else
451                         tprintf("%u, ", sev.sigev_signo);
452                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
453                 tprintf(", ");
454                 if (sev.sigev_notify == SIGEV_THREAD_ID)
455                         /* _pad[0] is the _tid field which might not be
456                            present in the userlevel definition of the
457                            struct.  */
458                         tprintf("{%d}", sev._sigev_un._pad[0]);
459                 else if (sev.sigev_notify == SIGEV_THREAD)
460                         tprintf("{%p, %p}", sev.sigev_notify_function,
461                                 sev.sigev_notify_attributes);
462                 else
463                         tprintf("{...}");
464                 tprintf("}");
465         }
466 }
467
468 int
469 sys_timer_create(tcp)
470 struct tcb *tcp;
471 {
472         if (entering(tcp)) {
473                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
474                 tprintf(", ");
475                 printsigevent(tcp, tcp->u_arg[1]);
476                 tprintf(", ");
477         } else {
478                 if (syserror(tcp))
479                         tprintf("%#lx", tcp->u_arg[2]);
480                 else {
481                         void *p;
482                         umove(tcp, tcp->u_arg[2], &p);
483                         tprintf("{%p}", p);
484                 }
485         }
486         return 0;
487 }
488
489 int
490 sys_timer_settime(tcp)
491 struct tcb *tcp;
492 {
493         if (entering(tcp)) {
494                 tprintf("%#lx, ", tcp->u_arg[0]);
495                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
496                 tprintf(", ");
497                 printitv(tcp, tcp->u_arg[2]);
498                 tprintf(", ");
499         } else {
500                 if (syserror(tcp))
501                         tprintf("%#lx", tcp->u_arg[3]);
502                 else
503                         printitv(tcp, tcp->u_arg[3]);
504         }
505         return 0;
506 }
507
508 int
509 sys_timer_gettime(tcp)
510 struct tcb *tcp;
511 {
512         if (entering(tcp)) {
513                 tprintf("%#lx, ", tcp->u_arg[0]);
514         } else {
515                 if (syserror(tcp))
516                         tprintf("%#lx", tcp->u_arg[1]);
517                 else
518                         printitv(tcp, tcp->u_arg[1]);
519         }
520         return 0;
521 }
522
523 static void
524 print_rtc(tcp, rt)
525 struct tcb *tcp;
526 const struct rtc_time *rt;
527 {
528         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
529                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
530                 rt->tm_sec, rt->tm_min, rt->tm_hour,
531                 rt->tm_mday, rt->tm_mon, rt->tm_year);
532         if (!abbrev(tcp))
533                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
534                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
535         else
536                 tprintf("...}");
537 }
538
539 int
540 rtc_ioctl(tcp, code, arg)
541 struct tcb *tcp;
542 long code;
543 long arg;
544 {
545         switch (code) {
546         case RTC_ALM_SET:
547         case RTC_SET_TIME:
548                 if (entering(tcp)) {
549                         struct rtc_time rt;
550                         if (umove(tcp, arg, &rt) < 0)
551                                 tprintf(", %#lx", arg);
552                         else {
553                                 tprintf(", ");
554                                 print_rtc(tcp, &rt);
555                         }
556                 }
557                 break;
558         case RTC_ALM_READ:
559         case RTC_RD_TIME:
560                 if (exiting(tcp)) {
561                         struct rtc_time rt;
562                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
563                                 tprintf(", %#lx", arg);
564                         else {
565                                 tprintf(", ");
566                                 print_rtc(tcp, &rt);
567                         }
568                 }
569                 break;
570         case RTC_IRQP_SET:
571         case RTC_EPOCH_SET:
572                 if (entering(tcp))
573                         tprintf(", %lu", arg);
574                 break;
575         case RTC_IRQP_READ:
576         case RTC_EPOCH_READ:
577                 if (exiting(tcp))
578                         tprintf(", %lu", arg);
579                 break;
580         case RTC_WKALM_SET:
581                 if (entering(tcp)) {
582                         struct rtc_wkalrm wk;
583                         if (umove(tcp, arg, &wk) < 0)
584                                 tprintf(", %#lx", arg);
585                         else {
586                                 tprintf(", {enabled=%d, pending=%d, ",
587                                         wk.enabled, wk.pending);
588                                 print_rtc(tcp, &wk.time);
589                                 tprintf("}");
590                         }
591                 }
592                 break;
593         case RTC_WKALM_RD:
594                 if (exiting(tcp)) {
595                         struct rtc_wkalrm wk;
596                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
597                                 tprintf(", %#lx", arg);
598                         else {
599                                 tprintf(", {enabled=%d, pending=%d, ",
600                                         wk.enabled, wk.pending);
601                                 print_rtc(tcp, &wk.time);
602                                 tprintf("}");
603                         }
604                 }
605                 break;
606         default:
607                 if (entering(tcp))
608                         tprintf(", %#lx", arg);
609                 break;
610         }
611         return 1;
612 }
613 #endif /* LINUX */