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