summaryrefslogtreecommitdiff
path: root/src/desc.c
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@strace.io>2021-02-03 08:00:00 +0000
committerDmitry V. Levin <ldv@strace.io>2021-02-03 08:00:00 +0000
commitecb3ed78107c851f71696df6730a15afff91ed3d (patch)
tree0b3d2b083040fc9b08d129f80d027ff41b995059 /src/desc.c
parentc47943de06204a269e16f732e7c9c71d4284b23f (diff)
downloadstrace-ecb3ed78107c851f71696df6730a15afff91ed3d.tar.gz
Move source files into src subdirectory
* src/Makefile.am: New file. * src/.gitignore: Likewise. * scno.am: Move into src subdirectory. * scno.head: Likewise. * strace-graph: Likewise. * strace-log-merge: Likewise. * linux/: Likewise. * types/: Likewise. * xlat/: Likewise. * *.awk: Likewise. * *.c: Likewise. * *.h: Likewise. * *.sh: Likewise. * .gitignore: Update. * Makefile.am: Update. * bootstrap: Update. * configure.ac: Update. * debian/rules: Update. * debian/strace-udeb.install: Update. * debian/strace.examples: Update. * debian/strace.install: Update. * debian/strace64.install: Update. * m4/gen_bpf_attr_m4.sh: Update. * m4/mpers.m4: Update. * tests/Makefile.am: Update. * tests/init.sh: Update. * tests/legacy_syscall_info.test: Update. * tests/strace-log-merge-error.test: Update. * tests/strace-log-merge-suffix.test: Update.
Diffstat (limited to 'src/desc.c')
-rw-r--r--src/desc.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/desc.c b/src/desc.c
new file mode 100644
index 000000000..ac4585f17
--- /dev/null
+++ b/src/desc.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
+ * 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-2020 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+#include "xstring.h"
+
+SYS_FUNC(close)
+{
+ printfd(tcp, tcp->u_arg[0]);
+
+ return RVAL_DECODED;
+}
+
+static int
+decode_select(struct tcb *const tcp, const kernel_ulong_t *const args,
+ const print_obj_by_addr_fn print_tv_ts,
+ const sprint_obj_by_addr_fn sprint_tv_ts)
+{
+ int i, j;
+ int nfds, fdsize;
+ fd_set *fds = NULL;
+ const char *sep;
+ kernel_ulong_t addr;
+
+ /* Kernel truncates args[0] to int, we do the same. */
+ nfds = (int) args[0];
+
+ /* Kernel rejects negative nfds, so we don't parse it either. */
+ if (nfds < 0)
+ nfds = 0;
+
+ /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
+ if (nfds > 1024*1024)
+ nfds = 1024*1024;
+
+ /*
+ * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below.
+ * Instead of args[0], use nfds for fd count, fdsize for array lengths.
+ */
+ fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
+
+ if (entering(tcp)) {
+ tprintf("%d", (int) args[0]);
+
+ if (verbose(tcp) && fdsize > 0)
+ fds = malloc(fdsize);
+ for (i = 0; i < 3; i++) {
+ addr = args[i+1];
+ tprints(", ");
+ if (!fds) {
+ printaddr(addr);
+ continue;
+ }
+ if (umoven_or_printaddr(tcp, addr, fdsize, fds))
+ continue;
+ tprints("[");
+ for (j = 0, sep = "";; j++) {
+ j = next_set_bit(fds, j, nfds);
+ if (j < 0)
+ break;
+ tprints(sep);
+ printfd(tcp, j);
+ sep = " ";
+ }
+ tprints("]");
+ }
+ free(fds);
+ tprints(", ");
+ print_tv_ts(tcp, args[4]);
+ } else {
+ static char outstr[1024];
+ char *outptr;
+#define end_outstr (outstr + sizeof(outstr))
+ int ready_fds;
+
+ if (syserror(tcp))
+ return 0;
+
+ ready_fds = tcp->u_rval;
+ if (ready_fds == 0) {
+ tcp->auxstr = "Timeout";
+ return RVAL_STR;
+ }
+
+ fds = malloc(fdsize);
+
+ outptr = outstr;
+ sep = "";
+ for (i = 0; i < 3 && ready_fds > 0; i++) {
+ int first = 1;
+
+ addr = args[i+1];
+ if (!addr || !fds || umoven(tcp, addr, fdsize, fds) < 0)
+ continue;
+ for (j = 0;; j++) {
+ j = next_set_bit(fds, j, nfds);
+ if (j < 0)
+ break;
+ /* +2 chars needed at the end: ']',NUL */
+ if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
+ if (first) {
+ outptr = xappendstr(outstr,
+ outptr,
+ "%s%s [%u",
+ sep,
+ i == 0 ? "in" : i == 1 ? "out" : "except",
+ j
+ );
+ first = 0;
+ sep = ", ";
+ } else {
+ outptr = xappendstr(outstr,
+ outptr,
+ " %u", j);
+ }
+ }
+ if (--ready_fds == 0)
+ break;
+ }
+ if (outptr != outstr)
+ *outptr++ = ']';
+ }
+ free(fds);
+ /* This contains no useful information on SunOS. */
+ if (args[4]) {
+ const char *str = sprint_tv_ts(tcp, args[4]);
+ if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) {
+ outptr = xappendstr(outstr, outptr,
+ "%sleft %s", sep, str);
+ }
+ }
+ *outptr = '\0';
+ tcp->auxstr = outstr;
+ return RVAL_STR;
+#undef end_outstr
+ }
+ return 0;
+}
+
+#if HAVE_ARCH_OLD_SELECT
+SYS_FUNC(oldselect)
+{
+ kernel_ulong_t *args =
+ fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 5);
+
+ if (args) {
+ return decode_select(tcp, args, print_timeval, sprint_timeval);
+ } else {
+ if (entering(tcp))
+ printaddr(tcp->u_arg[0]);
+ return RVAL_DECODED;
+ }
+}
+#endif /* HAVE_ARCH_OLD_SELECT */
+
+#ifdef ALPHA
+SYS_FUNC(osf_select)
+{
+ return decode_select(tcp, tcp->u_arg, print_timeval32, sprint_timeval32);
+}
+#endif
+
+SYS_FUNC(select)
+{
+ return decode_select(tcp, tcp->u_arg, print_timeval, sprint_timeval);
+}
+
+static int
+do_pselect6(struct tcb *const tcp, const print_obj_by_addr_fn print_ts,
+ const sprint_obj_by_addr_fn sprint_ts)
+{
+ int rc = decode_select(tcp, tcp->u_arg, print_ts, sprint_ts);
+ if (entering(tcp)) {
+ tprints(", ");
+ print_kernel_sigset(tcp, tcp->u_arg[5]);
+ }
+
+ return rc;
+}
+
+#if HAVE_ARCH_TIME32_SYSCALLS
+SYS_FUNC(pselect6_time32)
+{
+ return do_pselect6(tcp, print_timespec32, sprint_timespec32);
+}
+#endif
+
+SYS_FUNC(pselect6_time64)
+{
+ return do_pselect6(tcp, print_timespec64, sprint_timespec64);
+}