* Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
* Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
* Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
+ * Copyright (c) 1999-2017 The strace developers.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id$
*/
#include "defs.h"
-
#include <sys/resource.h>
-#ifdef LINUX
-#include <sys/times.h>
-#include <linux/kernel.h>
-#include <sys/quota.h>
-#endif /* LINUX */
-#ifdef SUNOS4
-#include <ufs/quota.h>
-#endif /* SUNOS4 */
-#if defined(SVR4) || defined(FREEBSD)
-#include <sys/times.h>
-#include <sys/time.h>
-#endif
-
-#if HAVE_LONG_LONG_RLIM_T
-/*
- * Hacks for systems that have a long long rlim_t
- */
-
-#define rlimit64 rlimit /* Ugly hack */
-#define rlim64_t rlim_t /* Ugly hack */
-#define RLIM64_INFINITY RLIM_INFINITY /* You guessed it */
-#define sys_getrlimit64 sys_getrlimit
-#define sys_setrlimit64 sys_setrlimit
-#endif
-
-static struct xlat resources[] = {
-#ifdef RLIMIT_CPU
- { RLIMIT_CPU, "RLIMIT_CPU" },
-#endif
-#ifdef RLIMIT_FSIZE
- { RLIMIT_FSIZE, "RLIMIT_FSIZE" },
-#endif
-#ifdef RLIMIT_DATA
- { RLIMIT_DATA, "RLIMIT_DATA" },
-#endif
-#ifdef RLIMIT_STACK
- { RLIMIT_STACK, "RLIMIT_STACK" },
-#endif
-#ifdef RLIMIT_CORE
- { RLIMIT_CORE, "RLIMIT_CORE" },
-#endif
-#ifdef RLIMIT_RSS
- { RLIMIT_RSS, "RLIMIT_RSS" },
-#endif
-#ifdef RLIMIT_NPROC
- { RLIMIT_NPROC,"RLIMIT_NPROC" },
-#endif
-#ifdef RLIMIT_NOFILE
- { RLIMIT_NOFILE,"RLIMIT_NOFILE" },
-#endif
-#ifdef RLIMIT_MEMLOCK
- { RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK" },
-#endif
-#ifdef RLIMIT_VMEM
- { RLIMIT_VMEM, "RLIMIT_VMEM" },
-#endif
-#ifdef RLIMIT_AS
- { RLIMIT_AS, "RLIMIT_AS" },
-#endif
- { 0, NULL },
-};
+#include "xlat/resources.h"
-#if !HAVE_LONG_LONG_RLIM_T
-static char *
-sprintrlim(lim)
-long lim;
+static const char *
+sprint_rlim64(uint64_t lim)
{
- static char buf[32];
+ static char buf[sizeof(uint64_t)*3 + sizeof("*1024")];
- if (lim == RLIM_INFINITY)
- sprintf(buf, "RLIM_INFINITY");
- else if (lim > 1024 && lim%1024 == 0)
- sprintf(buf, "%ld*1024", lim/1024);
+ if (lim == UINT64_MAX)
+ return "RLIM64_INFINITY";
+
+ if (lim > 1024 && lim % 1024 == 0)
+ sprintf(buf, "%" PRIu64 "*1024", lim / 1024);
else
- sprintf(buf, "%ld", lim);
+ sprintf(buf, "%" PRIu64, lim);
return buf;
}
-int
-sys_getrlimit(tcp)
-struct tcb *tcp;
+static void
+print_rlimit64(struct tcb *const tcp, const kernel_ulong_t addr)
{
- struct rlimit rlim;
+ struct rlimit_64 {
+ uint64_t rlim_cur;
+ uint64_t rlim_max;
+ } rlim;
- if (entering(tcp)) {
- printxval(resources, tcp->u_arg[0], "RLIMIT_???");
- tprintf(", ");
+ if (!umove_or_printaddr(tcp, addr, &rlim)) {
+ tprintf("{rlim_cur=%s,", sprint_rlim64(rlim.rlim_cur));
+ tprintf(" rlim_max=%s}", sprint_rlim64(rlim.rlim_max));
}
- else {
- if (syserror(tcp) || !verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
- tprintf("{...}");
- else {
- tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur));
- tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max));
- }
- }
- return 0;
}
-int
-sys_setrlimit(tcp)
-struct tcb *tcp;
-{
- struct rlimit rlim;
-
- if (entering(tcp)) {
- printxval(resources, tcp->u_arg[0], "RLIMIT_???");
- tprintf(", ");
- if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
- tprintf("{...}");
- else {
- tprintf("{rlim_cur=%s,", sprintrlim(rlim.rlim_cur));
- tprintf(" rlim_max=%s}", sprintrlim(rlim.rlim_max));
- }
- }
- return 0;
-}
-#endif /* !HAVE_LONG_LONG_RLIM_T */
+#if !defined(current_wordsize) || current_wordsize == 4
-#if _LFS64_LARGEFILE || HAVE_LONG_LONG_RLIM_T
-static char *
-sprintrlim64(lim)
-rlim64_t lim;
+static const char *
+sprint_rlim32(uint32_t lim)
{
- static char buf[64];
+ static char buf[sizeof(uint32_t)*3 + sizeof("*1024")];
+
+ if (lim == UINT32_MAX)
+ return "RLIM_INFINITY";
- if (lim == RLIM64_INFINITY)
- sprintf(buf, "RLIM64_INFINITY");
- else if (lim > 1024 && lim%1024 == 0)
- sprintf(buf, "%lld*1024", (long long) lim/1024);
+ if (lim > 1024 && lim % 1024 == 0)
+ sprintf(buf, "%" PRIu32 "*1024", lim / 1024);
else
- sprintf(buf, "%lld", (long long) lim);
+ sprintf(buf, "%" PRIu32, lim);
return buf;
}
-int
-sys_getrlimit64(tcp)
-struct tcb *tcp;
+static void
+print_rlimit32(struct tcb *const tcp, const kernel_ulong_t addr)
{
- struct rlimit64 rlim;
+ struct rlimit_32 {
+ uint32_t rlim_cur;
+ uint32_t rlim_max;
+ } rlim;
- if (entering(tcp)) {
- printxval(resources, tcp->u_arg[0], "RLIMIT_???");
- tprintf(", ");
- }
- else {
- if (syserror(tcp) || !verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
- tprintf("{...}");
- else {
- tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur));
- tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max));
- }
+ if (!umove_or_printaddr(tcp, addr, &rlim)) {
+ tprintf("{rlim_cur=%s,", sprint_rlim32(rlim.rlim_cur));
+ tprintf(" rlim_max=%s}", sprint_rlim32(rlim.rlim_max));
}
- return 0;
}
-int
-sys_setrlimit64(tcp)
-struct tcb *tcp;
+static void
+decode_rlimit(struct tcb *const tcp, const kernel_ulong_t addr)
{
- struct rlimit64 rlim;
-
- if (entering(tcp)) {
- printxval(resources, tcp->u_arg[0], "RLIMIT_???");
- tprintf(", ");
- if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[1]);
- else if (umove(tcp, tcp->u_arg[1], &rlim) < 0)
- tprintf("{...}");
- else {
- tprintf("{rlim_cur=%s,", sprintrlim64(rlim.rlim_cur));
- tprintf(" rlim_max=%s}", sprintrlim64(rlim.rlim_max));
- }
- }
- return 0;
+ /*
+ * i386 is the only personality on X86_64 and X32
+ * with 32-bit rlim_t.
+ * When current_personality is X32, current_wordsize
+ * equals to 4 but rlim_t is 64-bit.
+ */
+ if (current_klongsize == 4)
+ print_rlimit32(tcp, addr);
+ else
+ print_rlimit64(tcp, addr);
}
-#endif /* _LFS64_LARGEFILES || HAVE_LONG_LONG_RLIM_T */
-#ifndef SVR4
+#else /* defined(current_wordsize) && current_wordsize != 4 */
-static struct xlat usagewho[] = {
- { RUSAGE_SELF, "RUSAGE_SELF" },
- { RUSAGE_CHILDREN, "RUSAGE_CHILDREN" },
-#ifdef RUSAGE_BOTH
- { RUSAGE_BOTH, "RUSAGE_BOTH" },
-#endif
- { 0, NULL },
-};
+# define decode_rlimit print_rlimit64
-#ifdef ALPHA
-void
-printrusage32(tcp, addr)
-struct tcb *tcp;
-long addr;
-{
- struct timeval32
- {
- unsigned tv_sec;
- unsigned tv_usec;
- };
- struct rusage32
- {
- struct timeval32 ru_utime; /* user time used */
- struct timeval32 ru_stime; /* system time used */
- long ru_maxrss; /* maximum resident set size */
- long ru_ixrss; /* integral shared memory size */
- long ru_idrss; /* integral unshared data size */
- long ru_isrss; /* integral unshared stack size */
- long ru_minflt; /* page reclaims */
- long ru_majflt; /* page faults */
- long ru_nswap; /* swaps */
- long ru_inblock; /* block input operations */
- long ru_oublock; /* block output operations */
- long ru_msgsnd; /* messages sent */
- long ru_msgrcv; /* messages received */
- long ru_nsignals; /* signals received */
- long ru_nvcsw; /* voluntary context switches */
- long ru_nivcsw; /* involuntary " */
- } ru;
-
- if (!addr)
- tprintf("NULL");
- else if (syserror(tcp) || !verbose(tcp))
- tprintf("%#lx", addr);
- else if (umove(tcp, addr, &ru) < 0)
- tprintf("{...}");
- else if (!abbrev(tcp)) {
- tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
- (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
- (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
- tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
- ru.ru_maxrss, ru.ru_ixrss);
- tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
- ru.ru_idrss, ru.ru_isrss);
- tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
- ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
- tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
- ru.ru_inblock, ru.ru_oublock);
- tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
- ru.ru_msgsnd, ru.ru_msgrcv);
- tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
- ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
- }
- else {
- tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
- (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
- (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
- }
-}
#endif
-void
-printrusage(tcp, addr)
-struct tcb *tcp;
-long addr;
-{
- struct rusage ru;
-
- if (!addr)
- tprintf("NULL");
- else if (syserror(tcp) || !verbose(tcp))
- tprintf("%#lx", addr);
- else if (umove(tcp, addr, &ru) < 0)
- tprintf("{...}");
- else if (!abbrev(tcp)) {
- tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ",
- (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
- (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
- tprintf("ru_maxrss=%lu, ru_ixrss=%lu, ",
- ru.ru_maxrss, ru.ru_ixrss);
- tprintf("ru_idrss=%lu, ru_isrss=%lu, ",
- ru.ru_idrss, ru.ru_isrss);
- tprintf("ru_minflt=%lu, ru_majflt=%lu, ru_nswap=%lu, ",
- ru.ru_minflt, ru.ru_majflt, ru.ru_nswap);
- tprintf("ru_inblock=%lu, ru_oublock=%lu, ",
- ru.ru_inblock, ru.ru_oublock);
- tprintf("ru_msgsnd=%lu, ru_msgrcv=%lu, ",
- ru.ru_msgsnd, ru.ru_msgrcv);
- tprintf("ru_nsignals=%lu, ru_nvcsw=%lu, ru_nivcsw=%lu}",
- ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw);
- }
- else {
- tprintf("{ru_utime={%lu, %lu}, ru_stime={%lu, %lu}, ...}",
- (long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
- (long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec);
- }
-}
-
-int
-sys_getrusage(tcp)
-struct tcb *tcp;
+SYS_FUNC(getrlimit)
{
if (entering(tcp)) {
- printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
- tprintf(", ");
+ printxval(resources, tcp->u_arg[0], "RLIMIT_???");
+ tprints(", ");
+ } else {
+ decode_rlimit(tcp, tcp->u_arg[1]);
}
- else
- printrusage(tcp, tcp->u_arg[1]);
return 0;
}
-#ifdef ALPHA
-int
-sys_osf_getrusage(tcp)
-struct tcb *tcp;
-{
- if (entering(tcp)) {
- printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
- tprintf(", ");
- }
- else
- printrusage32(tcp, tcp->u_arg[1]);
- return 0;
-}
-#endif /* ALPHA */
-
-#endif /* !SVR4 */
-
-#ifdef LINUX
-
-int
-sys_sysinfo(tcp)
-struct tcb *tcp;
+SYS_FUNC(setrlimit)
{
- struct sysinfo si;
+ printxval(resources, tcp->u_arg[0], "RLIMIT_???");
+ tprints(", ");
+ decode_rlimit(tcp, tcp->u_arg[1]);
- if (exiting(tcp)) {
- if (syserror(tcp) || !verbose(tcp))
- tprintf("%#lx", tcp->u_arg[0]);
- else if (umove(tcp, tcp->u_arg[0], &si) < 0)
- tprintf("{...}");
- else {
- tprintf("{uptime=%lu, loads=[%lu, %lu, %lu] ",
- si.uptime, si.loads[0], si.loads[1],
- si.loads[2]);
- tprintf("totalram=%lu, freeram=%lu, ",
- si.totalram, si.freeram);
- tprintf("sharedram=%lu, bufferram=%lu} ",
- si.sharedram, si.bufferram);
- tprintf("totalswap=%lu, freeswap=%lu, procs=%hu}",
- si.totalswap, si.freeswap, si.procs);
- }
- }
- return 0;
+ return RVAL_DECODED;
}
-#endif /* LINUX */
-
-static struct xlat priorities[] = {
- { PRIO_PROCESS, "PRIO_PROCESS" },
- { PRIO_PGRP, "PRIO_PGRP" },
- { PRIO_USER, "PRIO_USER" },
- { 0, NULL },
-};
-
-int
-sys_getpriority(tcp)
-struct tcb *tcp;
+SYS_FUNC(prlimit64)
{
if (entering(tcp)) {
- printxval(priorities, tcp->u_arg[0], "PRIO_???");
- tprintf(", %lu", tcp->u_arg[1]);
+ tprintf("%d, ", (int) tcp->u_arg[0]);
+ printxval(resources, tcp->u_arg[1], "RLIMIT_???");
+ tprints(", ");
+ print_rlimit64(tcp, tcp->u_arg[2]);
+ tprints(", ");
+ } else {
+ print_rlimit64(tcp, tcp->u_arg[3]);
}
return 0;
}
-int
-sys_setpriority(tcp)
-struct tcb *tcp;
+#include "xlat/usagewho.h"
+
+SYS_FUNC(getrusage)
{
if (entering(tcp)) {
- printxval(priorities, tcp->u_arg[0], "PRIO_???");
- tprintf(", %lu, %ld", tcp->u_arg[1], tcp->u_arg[2]);
- }
+ printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
+ tprints(", ");
+ } else
+ printrusage(tcp, tcp->u_arg[1]);
return 0;
}
-int
-sys_nice(tcp)
-struct tcb *tcp;
+#ifdef ALPHA
+SYS_FUNC(osf_getrusage)
{
- if (entering(tcp))
- tprintf("%ld", tcp->u_arg[0]);
+ if (entering(tcp)) {
+ printxval(usagewho, tcp->u_arg[0], "RUSAGE_???");
+ tprints(", ");
+ } else
+ printrusage32(tcp, tcp->u_arg[1]);
return 0;
}
+#endif /* ALPHA */
-#ifndef SUNOS4
+#include "xlat/priorities.h"
-int
-sys_times(tcp)
-struct tcb *tcp;
+SYS_FUNC(getpriority)
{
- struct tms tbuf;
+ printxval(priorities, tcp->u_arg[0], "PRIO_???");
+ tprintf(", %d", (int) tcp->u_arg[1]);
- if (exiting(tcp)) {
- if (tcp->u_arg[0] == 0)
- tprintf("NULL");
- else if (syserror(tcp))
- tprintf("%#lx", tcp->u_arg[0]);
- else if (umove(tcp, tcp->u_arg[0], &tbuf) < 0)
- tprintf("{...}");
- else {
- tprintf("{tms_utime=%lu, tms_stime=%lu, ",
- tbuf.tms_utime, tbuf.tms_stime);
- tprintf("tms_cutime=%lu, tms_cstime=%lu}",
- tbuf.tms_cutime, tbuf.tms_cstime);
- }
- }
- return 0;
+ return RVAL_DECODED;
}
-#endif /* !SUNOS4 */
-
-#ifdef LINUX
-
-static struct xlat quotacmds[] = {
- { Q_QUOTAON, "Q_QUOTAON" },
- { Q_QUOTAOFF, "Q_QUOTAOFF" },
- { Q_GETQUOTA, "Q_GETQUOTA" },
- { Q_SETQUOTA, "Q_SETQUOTA" },
- { Q_SETUSE, "Q_SETUSE" },
- { Q_SYNC, "Q_SYNC" },
- { Q_SETQLIM, "Q_SETQLIM" },
- { Q_GETSTATS, "Q_GETSTATS" },
- { Q_RSQUASH, "Q_RSQUASH" },
- { 0, NULL },
-};
-
-static struct xlat quotatypes[] = {
- { USRQUOTA, "USRQUOTA" },
- { GRPQUOTA, "GRPQUOTA" },
- { 0, NULL },
-};
-
-int
-sys_quotactl(tcp)
-struct tcb *tcp;
+SYS_FUNC(setpriority)
{
- if (entering(tcp)) {
- printxval(quotacmds, tcp->u_arg[0] >> SUBCMDSHIFT, "Q_???");
- tprintf("|");
- printxval(quotatypes, tcp->u_arg[0] & SUBCMDMASK, "???QUOTA");
- tprintf(", ");
- printstr(tcp, tcp->u_arg[1], -1);
- tprintf(", %lu, ", tcp->u_arg[2]);
- }
- else {
- struct dqblk dq;
+ printxval(priorities, tcp->u_arg[0], "PRIO_???");
+ tprintf(", %d, %d", (int) tcp->u_arg[1], (int) tcp->u_arg[2]);
- if (!tcp->u_arg[3])
- tprintf("NULL");
- else if (!verbose(tcp))
- tprintf("%#lx", tcp->u_arg[3]);
- else if (umoven(tcp, tcp->u_arg[3], sizeof(struct dqblk),
- (char *) &dq) < 0)
- tprintf("???");
- else {
- tprintf("{");
- tprintf("%u, ", dq.dqb_bhardlimit);
- tprintf("%u, ", dq.dqb_bsoftlimit);
- tprintf("%u, ", dq.dqb_curblocks);
- tprintf("%u, ", dq.dqb_ihardlimit);
- tprintf("%u, ", dq.dqb_isoftlimit);
- tprintf("%u, ", dq.dqb_curinodes);
- tprintf("%lu, ", dq.dqb_btime);
- tprintf("%lu", dq.dqb_itime);
- tprintf("}");
- }
-
- }
- return 0;
+ return RVAL_DECODED;
}
-
-#endif /* Linux */
-
-#if defined(SUNOS4) || defined(FREEBSD)
-
-#ifdef FREEBSD
-#include <ufs/ufs/quota.h>
-#endif
-
-static struct xlat quotacmds[] = {
- { Q_QUOTAON, "Q_QUOTAON" },
- { Q_QUOTAOFF, "Q_QUOTAOFF" },
- { Q_GETQUOTA, "Q_GETQUOTA" },
- { Q_SETQUOTA, "Q_SETQUOTA" },
-#ifdef Q_SETQLIM
- { Q_SETQLIM, "Q_SETQLIM" },
-#endif
-#ifdef Q_SETUSE
- { Q_SETUSE, "Q_SETUSE" },
-#endif
- { Q_SYNC, "Q_SYNC" },
- { 0, NULL },
-};
-
-int
-sys_quotactl(tcp)
-struct tcb *tcp;
-{
- /* fourth arg (addr) not interpreted here */
- if (entering(tcp)) {
-#ifdef SUNOS4
- printxval(quotacmds, tcp->u_arg[0], "Q_???");
- tprintf(", ");
- printstr(tcp, tcp->u_arg[1], -1);
-#endif
-#ifdef FREEBSD
- printpath(tcp, tcp->u_arg[0]);
- tprintf(", ");
- printxval(quotacmds, tcp->u_arg[1], "Q_???");
-#endif
- tprintf(", %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]);
- }
- return 0;
-}
-
-#endif /* SUNOS4 || FREEBSD */