]> granicus.if.org Git - strace/blob - time.c
2004-07-12 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 int
368 sys_clock_settime(tcp)
369 struct tcb *tcp;
370 {
371         if (entering(tcp)) {
372                 tprintf("%#lx, ", tcp->u_arg[0]);
373                 printtv(tcp, tcp->u_arg[1]);
374         }
375         return 0;
376 }
377
378 int
379 sys_clock_gettime(tcp)
380 struct tcb *tcp;
381 {
382         if (entering(tcp)) {
383                 tprintf("%#lx, ", tcp->u_arg[0]);
384         } else {
385                 if (syserror(tcp))
386                         tprintf("%#lx", tcp->u_arg[1]);
387                 else
388                         printtv(tcp, tcp->u_arg[1]);
389         }
390         return 0;
391 }
392
393 int
394 sys_clock_nanosleep(tcp)
395 struct tcb *tcp;
396 {
397         if (entering(tcp)) {
398                 tprintf("%#lx, ", tcp->u_arg[0]);
399                 printflags(clockflags, tcp->u_arg[1]);
400                 tprintf(", ");
401                 printtv(tcp, tcp->u_arg[2]);
402                 tprintf(", ");
403         } else {
404                 if (syserror(tcp))
405                         tprintf("%#lx", tcp->u_arg[3]);
406                 else
407                         printtv(tcp, tcp->u_arg[3]);
408         }
409         return 0;
410 }
411
412 #ifndef SIGEV_THREAD_ID
413 # define SIGEV_THREAD_ID 4
414 #endif
415 static struct xlat sigev_value[] = {
416         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
417         { SIGEV_NONE+1, "SIGEV_NONE" },
418         { SIGEV_THREAD+1, "SIGEV_THREAD" },
419         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
420         { 0, NULL }
421 };
422
423 void
424 printsigevent(tcp, arg)
425 struct tcb *tcp;
426 long arg;
427 {
428         struct sigevent sev;
429         if (umove (tcp, arg, &sev) < 0)
430                 tprintf("{...}");
431         else {
432                 tprintf("{%p, %u, ", sev.sigev_value.sival_ptr,
433                         sev.sigev_signo);
434                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
435                 tprintf(", ");
436                 if (sev.sigev_notify == SIGEV_THREAD_ID)
437                         /* _pad[0] is the _tid field which might not be
438                            present in the userlevel definition of the
439                            struct.  */
440                         tprintf("{%d}", sev._sigev_un._pad[0]);
441                 else if (sev.sigev_notify == SIGEV_THREAD)
442                         tprintf("{%p, %p}", sev.sigev_notify_function,
443                                 sev.sigev_notify_attributes);
444                 else
445                         tprintf("{...}");
446                 tprintf("}");
447         }
448 }
449
450 int
451 sys_timer_create(tcp)
452 struct tcb *tcp;
453 {
454         if (entering(tcp)) {
455                 tprintf("%#lx, ", tcp->u_arg[0]);
456                 printsigevent(tcp, tcp->u_arg[1]);
457                 tprintf(", ");
458         } else {
459                 if (syserror(tcp))
460                         tprintf("%#lx", tcp->u_arg[2]);
461                 else {
462                         void *p;
463                         umove(tcp, tcp->u_arg[2], &p);
464                         tprintf("{%p}", p);
465                 }
466         }
467         return 0;
468 }
469
470 int
471 sys_timer_settime(tcp)
472 struct tcb *tcp;
473 {
474         if (entering(tcp)) {
475                 tprintf("%#lx, ", tcp->u_arg[0]);
476                 printflags(clockflags, tcp->u_arg[1]);
477                 tprintf(", ");
478                 printitv(tcp, tcp->u_arg[2]);
479                 tprintf(", ");
480         } else {
481                 if (syserror(tcp))
482                         tprintf("%#lx", tcp->u_arg[3]);
483                 else
484                         printitv(tcp, tcp->u_arg[3]);
485         }
486         return 0;
487 }
488
489 int
490 sys_timer_gettime(tcp)
491 struct tcb *tcp;
492 {
493         if (entering(tcp)) {
494                 tprintf("%#lx, ", tcp->u_arg[0]);
495         } else {
496                 if (syserror(tcp))
497                         tprintf("%#lx", tcp->u_arg[1]);
498                 else
499                         printitv(tcp, tcp->u_arg[1]);
500         }
501         return 0;
502 }
503 #endif /* LINUX */
504