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