1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 3 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 4 * Copyright (c) 1999-2018 The strace developers. 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 30 #include "defs.h" 31 #include <poll.h> 32 #include "xstring.h" 33 34 #include "xlat/pollflags.h" 35 36 static bool 37 print_pollfd(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 38 { 39 const struct pollfd *fds = elem_buf; 40 41 tprints("{fd="); 42 printfd(tcp, fds->fd); 43 if (fds->fd >= 0) { 44 tprints(", events="); 45 printflags(pollflags, (unsigned short) fds->events, "POLL???"); 46 } 47 tprints("}"); 48 49 return true; 50 } 51 52 static void 53 decode_poll_entering(struct tcb *tcp) 54 { 55 const kernel_ulong_t addr = tcp->u_arg[0]; 56 const unsigned int nfds = tcp->u_arg[1]; 57 struct pollfd fds; 58 59 print_array(tcp, addr, nfds, &fds, sizeof(fds), 60 umoven_or_printaddr, print_pollfd, 0); 61 tprintf(", %u, ", nfds); 62 } 63 64 static int 65 decode_poll_exiting(struct tcb *const tcp, const kernel_ulong_t pts) 66 { 67 struct pollfd fds; 68 const unsigned int nfds = tcp->u_arg[1]; 69 const unsigned long size = sizeof(fds) * nfds; 70 const kernel_ulong_t start = tcp->u_arg[0]; 71 const kernel_ulong_t end = start + size; 72 kernel_ulong_t cur; 73 const unsigned int max_printed = 74 abbrev(tcp) ? max_strlen : -1U; 75 unsigned int printed; 76 77 static char outstr[1024]; 78 char *outptr; 79 #define end_outstr (outstr + sizeof(outstr)) 80 81 if (syserror(tcp)) 82 return 0; 83 if (tcp->u_rval == 0) { 84 tcp->auxstr = "Timeout"; 85 return RVAL_STR; 86 } 87 88 if (!verbose(tcp) || !start || !nfds || 89 size / sizeof(fds) != nfds || end < start) 90 return 0; 91 92 outptr = outstr; 93 94 for (printed = 0, cur = start; cur < end; cur += sizeof(fds)) { 95 if (umove(tcp, cur, &fds) < 0) { 96 if (outptr == outstr) 97 *outptr++ = '['; 98 else 99 outptr = stpcpy(outptr, ", "); 100 outptr = xappendstr(outstr, outptr, "%#" PRI_klx, cur); 101 break; 102 } 103 if (!fds.revents) 104 continue; 105 if (outptr == outstr) 106 *outptr++ = '['; 107 else 108 outptr = stpcpy(outptr, ", "); 109 if (printed >= max_printed) { 110 outptr = stpcpy(outptr, "..."); 111 break; 112 } 113 114 static const char fmt[] = "{fd=%d, revents="; 115 char fdstr[sizeof(fmt) + sizeof(int) * 3]; 116 xsprintf(fdstr, fmt, fds.fd); 117 118 const char *flagstr = sprintflags("", pollflags, 119 (unsigned short) fds.revents); 120 121 if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >= 122 end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) { 123 outptr = stpcpy(outptr, "..."); 124 break; 125 } 126 outptr = stpcpy(outptr, fdstr); 127 outptr = stpcpy(outptr, flagstr); 128 *outptr++ = '}'; 129 ++printed; 130 } 131 132 if (outptr != outstr) 133 *outptr++ = ']'; 134 135 *outptr = '\0'; 136 if (pts) { 137 const char *str = sprint_timespec(tcp, pts); 138 139 if (outptr + sizeof(", left ") + strlen(str) < end_outstr) { 140 outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left "); 141 outptr = stpcpy(outptr, str); 142 } else { 143 outptr = stpcpy(outptr, ", ..."); 144 } 145 } 146 147 if (outptr == outstr) 148 return 0; 149 150 tcp->auxstr = outstr; 151 return RVAL_STR; 152 #undef end_outstr 153 } 154 155 SYS_FUNC(poll) 156 { 157 if (entering(tcp)) { 158 decode_poll_entering(tcp); 159 int timeout = tcp->u_arg[2]; 160 161 #ifdef INFTIM 162 if (INFTIM == timeout) 163 tprints("INFTIM"); 164 else 165 #endif 166 tprintf("%d", timeout); 167 168 return 0; 169 } else { 170 return decode_poll_exiting(tcp, 0); 171 } 172 } 173 174 SYS_FUNC(ppoll) 175 { 176 if (entering(tcp)) { 177 decode_poll_entering(tcp); 178 179 print_timespec(tcp, tcp->u_arg[2]); 180 tprints(", "); 181 /* NB: kernel requires arg[4] == NSIG_BYTES */ 182 print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]); 183 tprintf(", %" PRI_klu, tcp->u_arg[4]); 184 185 return 0; 186 } else { 187 return decode_poll_exiting(tcp, tcp->u_arg[2]); 188 } 189 } 190