]> granicus.if.org Git - strace/blob - poll.c
Print unfetchable address in poll and ppoll decoders
[strace] / poll.c
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  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "defs.h"
30 #include <poll.h>
31
32 #include "xlat/pollflags.h"
33
34 static void
35 print_pollfd(struct tcb *tcp, const struct pollfd *fds)
36 {
37         tprints("{fd=");
38         printfd(tcp, fds->fd);
39         if (fds->fd >= 0) {
40                 tprints(", events=");
41                 printflags(pollflags, fds->events, "POLL???");
42         }
43         tprints("}");
44 }
45
46 static int
47 decode_poll_entering(struct tcb *tcp)
48 {
49         struct pollfd fds;
50         const unsigned int nfds = tcp->u_arg[1];
51         const unsigned long size = sizeof(fds) * nfds;
52         const unsigned long start = tcp->u_arg[0];
53         const unsigned long end = start + size;
54         unsigned long cur, abbrev_end;
55
56         if (!verbose(tcp) || !start || !nfds ||
57             size / sizeof(fds) != nfds || end < start) {
58                 printaddr(start);
59                 tprintf(", %u, ", nfds);
60                 return 0;
61         }
62
63         if (abbrev(tcp)) {
64                 abbrev_end = start + max_strlen * sizeof(fds);
65                 if (abbrev_end < start)
66                         abbrev_end = end;
67         } else {
68                 abbrev_end = end;
69         }
70
71         if (start >= abbrev_end || umove(tcp, start, &fds) < 0) {
72                 printaddr(start);
73                 tprintf(", %u, ", nfds);
74                 return 0;
75         }
76
77         tprints("[");
78         print_pollfd(tcp, &fds);
79         for (cur = start + sizeof(fds); cur < end; cur += sizeof(fds)) {
80                 tprints(", ");
81                 if (cur >= abbrev_end) {
82                         tprints("...");
83                         break;
84                 }
85                 if (umove_or_printaddr(tcp, cur, &fds))
86                         break;
87                 print_pollfd(tcp, &fds);
88
89         }
90         tprintf("], %u, ", nfds);
91
92         return 0;
93 }
94
95 static int
96 decode_poll_exiting(struct tcb *tcp, const long pts)
97 {
98         struct pollfd fds;
99         const unsigned int nfds = tcp->u_arg[1];
100         const unsigned long size = sizeof(fds) * nfds;
101         const unsigned long start = tcp->u_arg[0];
102         const unsigned long end = start + size;
103         unsigned long cur, abbrev_end;
104
105         static char outstr[1024];
106         char *outptr;
107 #define end_outstr (outstr + sizeof(outstr))
108
109         if (syserror(tcp))
110                 return 0;
111         if (tcp->u_rval == 0) {
112                 tcp->auxstr = "Timeout";
113                 return RVAL_STR;
114         }
115
116         if (!verbose(tcp) || !start || !nfds ||
117             size / sizeof(fds) != nfds || end < start)
118                 return 0;
119         if (abbrev(tcp)) {
120                 abbrev_end = start + max_strlen * sizeof(fds);
121                 if (abbrev_end < start)
122                         abbrev_end = end;
123         } else {
124                 abbrev_end = end;
125         }
126
127         outptr = outstr;
128
129         for (cur = start; cur < end; cur += sizeof(fds)) {
130                 if (umove(tcp, cur, &fds) < 0) {
131                         if (outptr == outstr)
132                                 *outptr++ = '[';
133                         else
134                                 outptr = stpcpy(outptr, ", ");
135                         outptr += sprintf(outptr, "%#lx", cur);
136                         break;
137                 }
138                 if (!fds.revents)
139                         continue;
140                 if (outptr == outstr)
141                         *outptr++ = '[';
142                 else
143                         outptr = stpcpy(outptr, ", ");
144                 if (cur >= abbrev_end) {
145                         outptr = stpcpy(outptr, "...");
146                         break;
147                 }
148
149                 static const char fmt[] = "{fd=%d, revents=";
150                 char fdstr[sizeof(fmt) + sizeof(int) * 3];
151                 sprintf(fdstr, fmt, fds.fd);
152
153                 const char *flagstr = sprintflags("", pollflags, fds.revents);
154
155                 if (outptr + strlen(fdstr) + strlen(flagstr) + 1 >=
156                     end_outstr - (2 + 2 * sizeof(long) + sizeof(", ], ..."))) {
157                         outptr = stpcpy(outptr, "...");
158                         break;
159                 }
160                 outptr = stpcpy(outptr, fdstr);
161                 outptr = stpcpy(outptr, flagstr);
162                 *outptr++ = '}';
163         }
164
165         if (outptr != outstr)
166                 *outptr++ = ']';
167
168         *outptr = '\0';
169         if (pts) {
170                 const char *str = sprint_timespec(tcp, pts);
171
172                 if (outptr + sizeof(", left ") + strlen(str) < end_outstr) {
173                         outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
174                         outptr = stpcpy(outptr, str);
175                 } else {
176                         outptr = stpcpy(outptr, ", ...");
177                 }
178         }
179
180         if (outptr == outstr)
181                 return 0;
182
183         tcp->auxstr = outstr;
184         return RVAL_STR;
185 #undef end_outstr
186 }
187
188 SYS_FUNC(poll)
189 {
190         if (entering(tcp)) {
191                 int rc = decode_poll_entering(tcp);
192
193 #ifdef INFTIM
194                 if (INFTIM == (int) tcp->u_arg[2])
195                         tprints("INFTIM");
196                 else
197 #endif
198                         tprintf("%d", (int) tcp->u_arg[2]);
199
200                 return rc;
201         } else {
202                 return decode_poll_exiting(tcp, 0);
203         }
204 }
205
206 SYS_FUNC(ppoll)
207 {
208         if (entering(tcp)) {
209                 int rc = decode_poll_entering(tcp);
210
211                 print_timespec(tcp, tcp->u_arg[2]);
212                 tprints(", ");
213                 /* NB: kernel requires arg[4] == NSIG / 8 */
214                 print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
215                 tprintf(", %lu", tcp->u_arg[4]);
216
217                 return rc;
218         } else {
219                 return decode_poll_exiting(tcp, tcp->u_arg[2]);
220         }
221 }