]> granicus.if.org Git - strace/blob - time.c
.
[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                 if (printflags(clockflags, tcp->u_arg[1]) == 0)
415                         tprintf("0");
416                 tprintf(", ");
417                 printtv(tcp, tcp->u_arg[2]);
418                 tprintf(", ");
419         } else {
420                 if (syserror(tcp))
421                         tprintf("%#lx", tcp->u_arg[3]);
422                 else
423                         printtv(tcp, tcp->u_arg[3]);
424         }
425         return 0;
426 }
427
428 #ifndef SIGEV_THREAD_ID
429 # define SIGEV_THREAD_ID 4
430 #endif
431 static const struct xlat sigev_value[] = {
432         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
433         { SIGEV_NONE+1, "SIGEV_NONE" },
434         { SIGEV_THREAD+1, "SIGEV_THREAD" },
435         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
436         { 0, NULL }
437 };
438
439 void
440 printsigevent(tcp, arg)
441 struct tcb *tcp;
442 long arg;
443 {
444         struct sigevent sev;
445         if (umove (tcp, arg, &sev) < 0)
446                 tprintf("{...}");
447         else {
448                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
449                 if (sev.sigev_notify == SIGEV_SIGNAL)
450                         tprintf("%s, ", signame(sev.sigev_signo));
451                 else
452                         tprintf("%u, ", sev.sigev_signo);
453                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
454                 tprintf(", ");
455                 if (sev.sigev_notify == SIGEV_THREAD_ID)
456                         /* _pad[0] is the _tid field which might not be
457                            present in the userlevel definition of the
458                            struct.  */
459                         tprintf("{%d}", sev._sigev_un._pad[0]);
460                 else if (sev.sigev_notify == SIGEV_THREAD)
461                         tprintf("{%p, %p}", sev.sigev_notify_function,
462                                 sev.sigev_notify_attributes);
463                 else
464                         tprintf("{...}");
465                 tprintf("}");
466         }
467 }
468
469 int
470 sys_timer_create(tcp)
471 struct tcb *tcp;
472 {
473         if (entering(tcp)) {
474                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
475                 tprintf(", ");
476                 printsigevent(tcp, tcp->u_arg[1]);
477                 tprintf(", ");
478         } else {
479                 if (syserror(tcp))
480                         tprintf("%#lx", tcp->u_arg[2]);
481                 else {
482                         void *p;
483                         umove(tcp, tcp->u_arg[2], &p);
484                         tprintf("{%p}", p);
485                 }
486         }
487         return 0;
488 }
489
490 int
491 sys_timer_settime(tcp)
492 struct tcb *tcp;
493 {
494         if (entering(tcp)) {
495                 tprintf("%#lx, ", tcp->u_arg[0]);
496                 if (printflags(clockflags, tcp->u_arg[1]) == 0)
497                         tprintf("0");
498                 tprintf(", ");
499                 printitv(tcp, tcp->u_arg[2]);
500                 tprintf(", ");
501         } else {
502                 if (syserror(tcp))
503                         tprintf("%#lx", tcp->u_arg[3]);
504                 else
505                         printitv(tcp, tcp->u_arg[3]);
506         }
507         return 0;
508 }
509
510 int
511 sys_timer_gettime(tcp)
512 struct tcb *tcp;
513 {
514         if (entering(tcp)) {
515                 tprintf("%#lx, ", tcp->u_arg[0]);
516         } else {
517                 if (syserror(tcp))
518                         tprintf("%#lx", tcp->u_arg[1]);
519                 else
520                         printitv(tcp, tcp->u_arg[1]);
521         }
522         return 0;
523 }
524
525 static void
526 print_rtc(tcp, rt)
527 struct tcb *tcp;
528 const struct rtc_time *rt;
529 {
530         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
531                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
532                 rt->tm_sec, rt->tm_min, rt->tm_hour,
533                 rt->tm_mday, rt->tm_mon, rt->tm_year);
534         if (!abbrev(tcp))
535                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
536                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
537         else
538                 tprintf("...}");
539 }
540
541 int
542 rtc_ioctl(tcp, code, arg)
543 struct tcb *tcp;
544 long code;
545 long arg;
546 {
547         switch (code) {
548         case RTC_ALM_SET:
549         case RTC_SET_TIME:
550                 if (entering(tcp)) {
551                         struct rtc_time rt;
552                         if (umove(tcp, arg, &rt) < 0)
553                                 tprintf(", %#lx", arg);
554                         else {
555                                 tprintf(", ");
556                                 print_rtc(tcp, &rt);
557                         }
558                 }
559                 break;
560         case RTC_ALM_READ:
561         case RTC_RD_TIME:
562                 if (exiting(tcp)) {
563                         struct rtc_time rt;
564                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
565                                 tprintf(", %#lx", arg);
566                         else {
567                                 tprintf(", ");
568                                 print_rtc(tcp, &rt);
569                         }
570                 }
571                 break;
572         case RTC_IRQP_SET:
573         case RTC_EPOCH_SET:
574                 if (entering(tcp))
575                         tprintf(", %lu", arg);
576                 break;
577         case RTC_IRQP_READ:
578         case RTC_EPOCH_READ:
579                 if (exiting(tcp))
580                         tprintf(", %lu", arg);
581                 break;
582         case RTC_WKALM_SET:
583                 if (entering(tcp)) {
584                         struct rtc_wkalrm wk;
585                         if (umove(tcp, arg, &wk) < 0)
586                                 tprintf(", %#lx", arg);
587                         else {
588                                 tprintf(", {enabled=%d, pending=%d, ",
589                                         wk.enabled, wk.pending);
590                                 print_rtc(tcp, &wk.time);
591                                 tprintf("}");
592                         }
593                 }
594                 break;
595         case RTC_WKALM_RD:
596                 if (exiting(tcp)) {
597                         struct rtc_wkalrm wk;
598                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
599                                 tprintf(", %#lx", arg);
600                         else {
601                                 tprintf(", {enabled=%d, pending=%d, ",
602                                         wk.enabled, wk.pending);
603                                 print_rtc(tcp, &wk.time);
604                                 tprintf("}");
605                         }
606                 }
607                 break;
608         default:
609                 if (entering(tcp))
610                         tprintf(", %#lx", arg);
611                 break;
612         }
613         return 1;
614 }
615 #endif /* LINUX */