]> granicus.if.org Git - strace/blob - resource.c
Optimize code if we have only one personality
[strace] / resource.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  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "defs.h"
32 #include <sys/resource.h>
33 #include <sys/times.h>
34 #include <linux/kernel.h>
35
36 static const struct xlat resources[] = {
37 #ifdef RLIMIT_AS
38         { RLIMIT_AS,            "RLIMIT_AS"             },
39 #endif
40 #ifdef RLIMIT_CORE
41         { RLIMIT_CORE,          "RLIMIT_CORE"           },
42 #endif
43 #ifdef RLIMIT_CPU
44         { RLIMIT_CPU,           "RLIMIT_CPU"            },
45 #endif
46 #ifdef RLIMIT_DATA
47         { RLIMIT_DATA,          "RLIMIT_DATA"           },
48 #endif
49 #ifdef RLIMIT_FSIZE
50         { RLIMIT_FSIZE,         "RLIMIT_FSIZE"          },
51 #endif
52 #ifdef RLIMIT_LOCKS
53         { RLIMIT_LOCKS,         "RLIMIT_LOCKS"          },
54 #endif
55 #ifdef RLIMIT_MEMLOCK
56         { RLIMIT_MEMLOCK,       "RLIMIT_MEMLOCK"        },
57 #endif
58 #ifdef RLIMIT_MSGQUEUE
59         { RLIMIT_MSGQUEUE,      "RLIMIT_MSGQUEUE"       },
60 #endif
61 #ifdef RLIMIT_NICE
62         { RLIMIT_NICE,          "RLIMIT_NICE"           },
63 #endif
64 #ifdef RLIMIT_NOFILE
65         { RLIMIT_NOFILE,        "RLIMIT_NOFILE"         },
66 #endif
67 #ifdef RLIMIT_NPROC
68         { RLIMIT_NPROC,         "RLIMIT_NPROC"          },
69 #endif
70 #ifdef RLIMIT_RSS
71         { RLIMIT_RSS,           "RLIMIT_RSS"            },
72 #endif
73 #ifdef RLIMIT_RTPRIO
74         { RLIMIT_RTPRIO,        "RLIMIT_RTPRIO"         },
75 #endif
76 #ifdef RLIMIT_RTTIME
77         { RLIMIT_RTTIME,        "RLIMIT_RTTIME"         },
78 #endif
79 #ifdef RLIMIT_SIGPENDING
80         { RLIMIT_SIGPENDING,    "RLIMIT_SIGPENDING"     },
81 #endif
82 #ifdef RLIMIT_STACK
83         { RLIMIT_STACK,         "RLIMIT_STACK"          },
84 #endif
85 #ifdef RLIMIT_VMEM
86         { RLIMIT_VMEM,          "RLIMIT_VMEM"           },
87 #endif
88         { 0,                    NULL                    }
89 };
90
91 #if !(SIZEOF_RLIM_T == 4 || SIZEOF_RLIM_T == 8)
92 # error "Unsupported SIZEOF_RLIM_T value"
93 #endif
94
95 static const char *
96 sprint_rlim64(uint64_t lim)
97 {
98         static char buf[sizeof(uint64_t)*3 + sizeof("*1024")];
99
100         if (lim == UINT64_MAX)
101                 return "RLIM64_INFINITY";
102
103         if (lim > 1024 && lim % 1024 == 0)
104                 sprintf(buf, "%" PRIu64 "*1024", lim / 1024);
105         else
106                 sprintf(buf, "%" PRIu64, lim);
107         return buf;
108 }
109
110 static void
111 print_rlimit64(struct tcb *tcp, unsigned long addr)
112 {
113         struct rlimit_64 {
114                 uint64_t rlim_cur;
115                 uint64_t rlim_max;
116         } rlim;
117
118         if (umove(tcp, addr, &rlim) < 0)
119                 tprintf("%#lx", addr);
120         else {
121                 tprintf("{rlim_cur=%s,", sprint_rlim64(rlim.rlim_cur));
122                 tprintf(" rlim_max=%s}", sprint_rlim64(rlim.rlim_max));
123         }
124 }
125
126 static void
127 decode_rlimit64(struct tcb *tcp, unsigned long addr)
128 {
129         if (!addr)
130                 tprints("NULL");
131         else if (!verbose(tcp) ||
132                  (exiting(tcp) && syserror(tcp)))
133                 tprintf("%#lx", addr);
134         else
135                 print_rlimit64(tcp, addr);
136 }
137
138 #if SIZEOF_RLIM_T == 4 || SUPPORTED_PERSONALITIES > 1
139
140 static const char *
141 sprint_rlim32(uint32_t lim)
142 {
143         static char buf[sizeof(uint32_t)*3 + sizeof("*1024")];
144
145         if (lim == UINT32_MAX)
146                 return "RLIM_INFINITY";
147
148         if (lim > 1024 && lim % 1024 == 0)
149                 sprintf(buf, "%" PRIu32 "*1024", lim / 1024);
150         else
151                 sprintf(buf, "%" PRIu32, lim);
152         return buf;
153 }
154
155 static void
156 print_rlimit32(struct tcb *tcp, unsigned long addr)
157 {
158         struct rlimit_32 {
159                 uint32_t rlim_cur;
160                 uint32_t rlim_max;
161         } rlim;
162
163         if (umove(tcp, addr, &rlim) < 0)
164                 tprintf("%#lx", addr);
165         else {
166                 tprintf("{rlim_cur=%s,", sprint_rlim32(rlim.rlim_cur));
167                 tprintf(" rlim_max=%s}", sprint_rlim32(rlim.rlim_max));
168         }
169 }
170
171 static void
172 decode_rlimit(struct tcb *tcp, unsigned long addr)
173 {
174         if (!addr)
175                 tprints("NULL");
176         else if (!verbose(tcp) ||
177                  (exiting(tcp) && syserror(tcp)))
178                 tprintf("%#lx", addr);
179         else {
180 # if SIZEOF_RLIM_T == 4
181                 print_rlimit32(tcp, addr);
182 # else
183                 if (current_wordsize == 4)
184                         print_rlimit32(tcp, addr);
185                 else
186                         print_rlimit64(tcp, addr);
187 # endif
188         }
189 }
190
191 #else /* SIZEOF_RLIM_T == 8 && SUPPORTED_PERSONALITIES == 1 */
192
193 # define decode_rlimit decode_rlimit64
194
195 #endif /* SIZEOF_RLIM_T == 4 || SUPPORTED_PERSONALITIES > 1 */
196
197 int
198 sys_getrlimit(struct tcb *tcp)
199 {
200         if (entering(tcp)) {
201                 printxval(resources, tcp->u_arg[0], "RLIMIT_???");
202                 tprints(", ");
203         }
204         else {
205                 decode_rlimit(tcp, tcp->u_arg[1]);
206         }
207         return 0;
208 }
209
210 int
211 sys_setrlimit(struct tcb *tcp)
212 {
213         if (entering(tcp)) {
214                 printxval(resources, tcp->u_arg[0], "RLIMIT_???");
215                 tprints(", ");
216                 decode_rlimit(tcp, tcp->u_arg[1]);
217         }
218         return 0;
219 }
220
221 int
222 sys_prlimit64(struct tcb *tcp)
223 {
224         if (entering(tcp)) {
225                 tprintf("%ld, ", tcp->u_arg[0]);
226                 printxval(resources, tcp->u_arg[1], "RLIMIT_???");
227                 tprints(", ");
228                 decode_rlimit64(tcp, tcp->u_arg[2]);
229                 tprints(", ");
230         } else {
231                 decode_rlimit64(tcp, tcp->u_arg[3]);
232         }
233         return 0;
234 }
235
236 static const struct xlat usagewho[] = {
237         { RUSAGE_SELF,          "RUSAGE_SELF"           },
238         { RUSAGE_CHILDREN,      "RUSAGE_CHILDREN"       },
239 #ifdef RUSAGE_BOTH
240         { RUSAGE_BOTH,          "RUSAGE_BOTH"           },
241 #endif
242         { 0,                    NULL                    },
243 };
244
245 #ifdef ALPHA
246 void
247 printrusage32(struct tcb *tcp, long addr)
248 {
249         struct timeval32 {
250                 unsigned tv_sec;
251                 unsigned tv_usec;
252         };
253         struct rusage32 {
254                 struct timeval32 ru_utime;      /* user time used */
255                 struct timeval32 ru_stime;      /* system time used */
256                 long    ru_maxrss;              /* maximum resident set size */
257                 long    ru_ixrss;               /* integral shared memory size */
258                 long    ru_idrss;               /* integral unshared data size */
259                 long    ru_isrss;               /* integral unshared stack size */
260                 long    ru_minflt;              /* page reclaims */
261                 long    ru_majflt;              /* page faults */
262                 long    ru_nswap;               /* swaps */
263                 long    ru_inblock;             /* block input operations */
264                 long    ru_oublock;             /* block output operations */
265                 long    ru_msgsnd;              /* messages sent */
266                 long    ru_msgrcv;              /* messages received */
267                 long    ru_nsignals;            /* signals received */
268                 long    ru_nvcsw;               /* voluntary context switches */
269                 long    ru_nivcsw;              /* involuntary " */
270         } ru;
271
272         if (!addr)
273                 tprints("NULL");
274         else if (syserror(tcp) || !verbose(tcp))
275                 tprintf("%#lx", addr);
276         else if (umove(tcp, addr, &ru) < 0)
277                 tprints("{...}");
278         else if (!abbrev(tcp)) {
279                 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
280                         (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
281                         (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
282                 tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
283                         ru.ru_maxrss, ru.ru_ixrss);
284                 tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
285                         ru.ru_idrss, ru.ru_isrss);
286                 tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
287                         ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
288                 tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
289                         ru.ru_inblock, ru.ru_oublock);
290                 tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
291                         ru.ru_msgsnd, ru.ru_msgrcv);
292                 tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
293                         ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
294         }
295         else {
296                 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
297                         (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
298                         (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
299         }
300 }
301 #endif
302
303 void
304 printrusage(struct tcb *tcp, long addr)
305 {
306         struct rusage ru;
307
308         if (!addr)
309                 tprints("NULL");
310         else if (syserror(tcp) || !verbose(tcp))
311                 tprintf("%#lx", addr);
312         else if (umove(tcp, addr, &ru) < 0)
313                 tprints("{...}");
314         else if (!abbrev(tcp)) {
315                 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
316                         (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
317                         (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
318                 tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
319                         ru.ru_maxrss, ru.ru_ixrss);
320                 tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
321                         ru.ru_idrss, ru.ru_isrss);
322                 tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
323                         ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
324                 tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
325                         ru.ru_inblock, ru.ru_oublock);
326                 tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
327                         ru.ru_msgsnd, ru.ru_msgrcv);
328                 tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
329                         ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
330         }
331         else {
332                 tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
333                         (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
334                         (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
335         }
336 }
337
338 int
339 sys_getrusage(struct tcb *tcp)
340 {
341         if (entering(tcp)) {
342                 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
343                 tprints(", ");
344         }
345         else
346                 printrusage(tcp, tcp->u_arg[1]);
347         return 0;
348 }
349
350 #ifdef ALPHA
351 int
352 sys_osf_getrusage(struct tcb *tcp)
353 {
354         if (entering(tcp)) {
355                 printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
356                 tprints(", ");
357         }
358         else
359                 printrusage32(tcp, tcp->u_arg[1]);
360         return 0;
361 }
362 #endif /* ALPHA */
363
364 int
365 sys_sysinfo(struct tcb *tcp)
366 {
367         struct sysinfo si;
368
369         if (exiting(tcp)) {
370                 if (syserror(tcp) || !verbose(tcp))
371                         tprintf("%#lx", tcp->u_arg[0]);
372                 else if (umove(tcp, tcp->u_arg[0], &si) < 0)
373                         tprints("{...}");
374                 else {
375                         tprintf("{uptime=%lu, loads=[%lu, %lu, %lu] ",
376                                 (long) si.uptime, (long) si.loads[0],
377                                 (long) si.loads[1], (long) si.loads[2]);
378                         tprintf("totalram=%lu, freeram=%lu, ",
379                                 (long) si.totalram, (long) si.freeram);
380                         tprintf("sharedram=%lu, bufferram=%lu} ",
381                                 (long) si.sharedram, (long) si.bufferram);
382                         tprintf("totalswap=%lu, freeswap=%lu, procs=%hu}",
383                                 (long) si.totalswap, (long) si.freeswap,
384                                 si.procs);
385                 }
386         }
387         return 0;
388 }
389
390 static const struct xlat priorities[] = {
391         { PRIO_PROCESS, "PRIO_PROCESS"  },
392         { PRIO_PGRP,    "PRIO_PGRP"     },
393         { PRIO_USER,    "PRIO_USER"     },
394         { 0,            NULL            },
395 };
396
397 int
398 sys_getpriority(struct tcb *tcp)
399 {
400         if (entering(tcp)) {
401                 printxval(priorities, tcp->u_arg[0], "PRIO_???");
402                 tprintf(", %lu", tcp->u_arg[1]);
403         }
404         return 0;
405 }
406
407 int
408 sys_setpriority(struct tcb *tcp)
409 {
410         if (entering(tcp)) {
411                 printxval(priorities, tcp->u_arg[0], "PRIO_???");
412                 tprintf(", %lu, %ld", tcp->u_arg[1], tcp->u_arg[2]);
413         }
414         return 0;
415 }
416
417 int
418 sys_times(struct tcb *tcp)
419 {
420         struct tms tbuf;
421
422         if (exiting(tcp)) {
423                 if (tcp->u_arg[0] == 0)
424                         tprints("NULL");
425                 else if (syserror(tcp))
426                         tprintf("%#lx", tcp->u_arg[0]);
427                 else if (umove(tcp, tcp->u_arg[0], &tbuf) < 0)
428                         tprints("{...}");
429                 else {
430                         tprintf("{tms_utime=%lu, tms_stime=%lu, ",
431                                 tbuf.tms_utime, tbuf.tms_stime);
432                         tprintf("tms_cutime=%lu, tms_cstime=%lu}",
433                                 tbuf.tms_cutime, tbuf.tms_cstime);
434                 }
435         }
436         return 0;
437 }