]> granicus.if.org Git - strace/blob - stream.c
Fix printstrbufarg's address argument to be long, not int
[strace] / stream.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 #ifdef HAVE_POLL_H
31 # include <poll.h>
32 #endif
33 #ifdef HAVE_SYS_POLL_H
34 # include <sys/poll.h>
35 #endif
36 #ifdef HAVE_STROPTS_H
37 # include <stropts.h>
38 #endif
39 #ifdef HAVE_SYS_CONF_H
40 # include <sys/conf.h>
41 #endif
42
43 #ifndef HAVE_STROPTS_H
44 #define RS_HIPRI 1
45 struct strbuf {
46         int     maxlen;                 /* no. of bytes in buffer */
47         int     len;                    /* no. of bytes returned */
48         const char *buf;                /* pointer to data */
49 };
50 #define MORECTL 1
51 #define MOREDATA 2
52 #endif /* !HAVE_STROPTS_H */
53
54 static const struct xlat msgflags[] = {
55         { RS_HIPRI,     "RS_HIPRI"      },
56         { 0,            NULL            },
57 };
58
59 static void
60 printstrbuf(struct tcb *tcp, struct strbuf *sbp, int getting)
61 {
62         if (sbp->maxlen == -1 && getting)
63                 tprints("{maxlen=-1}");
64         else {
65                 tprints("{");
66                 if (getting)
67                         tprintf("maxlen=%d, ", sbp->maxlen);
68                 tprintf("len=%d, buf=", sbp->len);
69                 printstr(tcp, (unsigned long) sbp->buf, sbp->len);
70                 tprints("}");
71         }
72 }
73
74 static void
75 printstrbufarg(struct tcb *tcp, long arg, int getting)
76 {
77         struct strbuf buf;
78
79         if (arg == 0)
80                 tprints("NULL");
81         else if (umove(tcp, arg, &buf) < 0)
82                 tprints("{...}");
83         else
84                 printstrbuf(tcp, &buf, getting);
85         tprints(", ");
86 }
87
88 int
89 sys_putmsg(struct tcb *tcp)
90 {
91         int i;
92
93         if (entering(tcp)) {
94                 /* fd */
95                 tprintf("%ld, ", tcp->u_arg[0]);
96                 /* control and data */
97                 for (i = 1; i < 3; i++)
98                         printstrbufarg(tcp, tcp->u_arg[i], 0);
99                 /* flags */
100                 printflags(msgflags, tcp->u_arg[3], "RS_???");
101         }
102         return 0;
103 }
104
105 #if defined(SPARC) || defined(SPARC64)
106 int
107 sys_getmsg(struct tcb *tcp)
108 {
109         int i, flags;
110
111         if (entering(tcp)) {
112                 /* fd */
113                 tprintf("%lu, ", tcp->u_arg[0]);
114         } else {
115                 if (syserror(tcp)) {
116                         tprintf("%#lx, %#lx, %#lx",
117                                 tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
118                         return 0;
119                 }
120                 /* control and data */
121                 for (i = 1; i < 3; i++)
122                         printstrbufarg(tcp, tcp->u_arg[i], 1);
123                 /* pointer to flags */
124                 if (tcp->u_arg[3] == 0)
125                         tprints("NULL");
126                 else if (umove(tcp, tcp->u_arg[3], &flags) < 0)
127                         tprints("[?]");
128                 else {
129                         tprints("[");
130                         printflags(msgflags, flags, "RS_???");
131                         tprints("]");
132                 }
133                 /* decode return value */
134                 switch (tcp->u_rval) {
135                 case MORECTL:
136                         tcp->auxstr = "MORECTL";
137                         break;
138                 case MORECTL|MOREDATA:
139                         tcp->auxstr = "MORECTL|MOREDATA";
140                         break;
141                 case MOREDATA:
142                         tcp->auxstr = "MORECTL";
143                         break;
144                 default:
145                         tcp->auxstr = NULL;
146                         break;
147                 }
148         }
149         return RVAL_HEX | RVAL_STR;
150 }
151 #endif
152
153 #if defined SYS_putpmsg || defined SYS_getpmsg
154 static const struct xlat pmsgflags[] = {
155 #ifdef MSG_HIPRI
156         { MSG_HIPRI,    "MSG_HIPRI"     },
157 #endif
158 #ifdef MSG_AND
159         { MSG_ANY,      "MSG_ANY"       },
160 #endif
161 #ifdef MSG_BAND
162         { MSG_BAND,     "MSG_BAND"      },
163 #endif
164         { 0,            NULL            },
165 };
166 #endif
167
168 #ifdef SYS_putpmsg
169 int
170 sys_putpmsg(struct tcb *tcp)
171 {
172         int i;
173
174         if (entering(tcp)) {
175                 /* fd */
176                 tprintf("%ld, ", tcp->u_arg[0]);
177                 /* control and data */
178                 for (i = 1; i < 3; i++)
179                         printstrbufarg(tcp, tcp->u_arg[i], 0);
180                 /* band */
181                 tprintf("%ld, ", tcp->u_arg[3]);
182                 /* flags */
183                 printflags(pmsgflags, tcp->u_arg[4], "MSG_???");
184         }
185         return 0;
186 }
187 #endif /* SYS_putpmsg */
188
189 #ifdef SYS_getpmsg
190 int
191 sys_getpmsg(struct tcb *tcp)
192 {
193         int i, flags;
194
195         if (entering(tcp)) {
196                 /* fd */
197                 tprintf("%lu, ", tcp->u_arg[0]);
198         } else {
199                 if (syserror(tcp)) {
200                         tprintf("%#lx, %#lx, %#lx, %#lx", tcp->u_arg[1],
201                                 tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[4]);
202                         return 0;
203                 }
204                 /* control and data */
205                 for (i = 1; i < 3; i++)
206                         printstrbufarg(tcp, tcp->u_arg[i], 1);
207                 /* pointer to band */
208                 printnum(tcp, tcp->u_arg[3], "%d");
209                 tprints(", ");
210                 /* pointer to flags */
211                 if (tcp->u_arg[4] == 0)
212                         tprints("NULL");
213                 else if (umove(tcp, tcp->u_arg[4], &flags) < 0)
214                         tprints("[?]");
215                 else {
216                         tprints("[");
217                         printflags(pmsgflags, flags, "MSG_???");
218                         tprints("]");
219                 }
220                 /* decode return value */
221                 switch (tcp->u_rval) {
222                 case MORECTL:
223                         tcp->auxstr = "MORECTL";
224                         break;
225                 case MORECTL|MOREDATA:
226                         tcp->auxstr = "MORECTL|MOREDATA";
227                         break;
228                 case MOREDATA:
229                         tcp->auxstr = "MORECTL";
230                         break;
231                 default:
232                         tcp->auxstr = NULL;
233                         break;
234                 }
235         }
236         return RVAL_HEX | RVAL_STR;
237 }
238 #endif /* SYS_getpmsg */
239
240 #ifdef HAVE_SYS_POLL_H
241
242 static const struct xlat pollflags[] = {
243 #ifdef POLLIN
244         { POLLIN,       "POLLIN"        },
245         { POLLPRI,      "POLLPRI"       },
246         { POLLOUT,      "POLLOUT"       },
247 #ifdef POLLRDNORM
248         { POLLRDNORM,   "POLLRDNORM"    },
249 #endif
250 #ifdef POLLWRNORM
251         { POLLWRNORM,   "POLLWRNORM"    },
252 #endif
253 #ifdef POLLRDBAND
254         { POLLRDBAND,   "POLLRDBAND"    },
255 #endif
256 #ifdef POLLWRBAND
257         { POLLWRBAND,   "POLLWRBAND"    },
258 #endif
259         { POLLERR,      "POLLERR"       },
260         { POLLHUP,      "POLLHUP"       },
261         { POLLNVAL,     "POLLNVAL"      },
262 #endif
263         { 0,            NULL            },
264 };
265
266 static int
267 decode_poll(struct tcb *tcp, long pts)
268 {
269         struct pollfd fds;
270         unsigned nfds;
271         unsigned long size, start, cur, end, abbrev_end;
272         int failed = 0;
273
274         if (entering(tcp)) {
275                 nfds = tcp->u_arg[1];
276                 size = sizeof(fds) * nfds;
277                 start = tcp->u_arg[0];
278                 end = start + size;
279                 if (nfds == 0 || size / sizeof(fds) != nfds || end < start) {
280                         tprintf("%#lx, %d, ",
281                                 tcp->u_arg[0], nfds);
282                         return 0;
283                 }
284                 if (abbrev(tcp)) {
285                         abbrev_end = start + max_strlen * sizeof(fds);
286                         if (abbrev_end < start)
287                                 abbrev_end = end;
288                 } else {
289                         abbrev_end = end;
290                 }
291                 tprints("[");
292                 for (cur = start; cur < end; cur += sizeof(fds)) {
293                         if (cur > start)
294                                 tprints(", ");
295                         if (cur >= abbrev_end) {
296                                 tprints("...");
297                                 break;
298                         }
299                         if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
300                                 tprints("?");
301                                 failed = 1;
302                                 break;
303                         }
304                         if (fds.fd < 0) {
305                                 tprintf("{fd=%d}", fds.fd);
306                                 continue;
307                         }
308                         tprints("{fd=");
309                         printfd(tcp, fds.fd);
310                         tprints(", events=");
311                         printflags(pollflags, fds.events, "POLL???");
312                         tprints("}");
313                 }
314                 tprints("]");
315                 if (failed)
316                         tprintf(" %#lx", start);
317                 tprintf(", %d, ", nfds);
318                 return 0;
319         } else {
320                 static char outstr[1024];
321                 char *outptr;
322 #define end_outstr (outstr + sizeof(outstr))
323                 const char *flagstr;
324
325                 if (syserror(tcp))
326                         return 0;
327                 if (tcp->u_rval == 0) {
328                         tcp->auxstr = "Timeout";
329                         return RVAL_STR;
330                 }
331
332                 nfds = tcp->u_arg[1];
333                 size = sizeof(fds) * nfds;
334                 start = tcp->u_arg[0];
335                 end = start + size;
336                 if (nfds == 0 || size / sizeof(fds) != nfds || end < start)
337                         return 0;
338                 if (abbrev(tcp)) {
339                         abbrev_end = start + max_strlen * sizeof(fds);
340                         if (abbrev_end < start)
341                                 abbrev_end = end;
342                 } else {
343                         abbrev_end = end;
344                 }
345
346                 outptr = outstr;
347
348                 for (cur = start; cur < end; cur += sizeof(fds)) {
349                         if (umoven(tcp, cur, sizeof fds, (char *) &fds) < 0) {
350                                 if (outptr < end_outstr - 2)
351                                         *outptr++ = '?';
352                                 failed = 1;
353                                 break;
354                         }
355                         if (!fds.revents)
356                                 continue;
357                         if (outptr == outstr) {
358                                 *outptr++ = '[';
359                         } else {
360                                 if (outptr < end_outstr - 3)
361                                         outptr = stpcpy(outptr, ", ");
362                         }
363                         if (cur >= abbrev_end) {
364                                 if (outptr < end_outstr - 4)
365                                         outptr = stpcpy(outptr, "...");
366                                 break;
367                         }
368                         if (outptr < end_outstr - (sizeof("{fd=%d, revents=") + sizeof(int)*3) + 1)
369                                 outptr += sprintf(outptr, "{fd=%d, revents=", fds.fd);
370                         flagstr = sprintflags("", pollflags, fds.revents);
371                         if (outptr < end_outstr - (strlen(flagstr) + 2)) {
372                                 outptr = stpcpy(outptr, flagstr);
373                                 *outptr++ = '}';
374                         }
375                 }
376                 if (failed)
377                         return 0;
378
379                 if (outptr != outstr /* && outptr < end_outstr - 1 (always true)*/)
380                         *outptr++ = ']';
381
382                 *outptr = '\0';
383                 if (pts) {
384                         if (outptr < end_outstr - (10 + TIMESPEC_TEXT_BUFSIZE)) {
385                                 outptr = stpcpy(outptr, outptr == outstr ? "left " : ", left ");
386                                 sprint_timespec(outptr, tcp, pts);
387                         }
388                 }
389
390                 if (outptr == outstr)
391                         return 0;
392
393                 tcp->auxstr = outstr;
394                 return RVAL_STR;
395 #undef end_outstr
396         }
397 }
398
399 int
400 sys_poll(struct tcb *tcp)
401 {
402         int rc = decode_poll(tcp, 0);
403         if (entering(tcp)) {
404 #ifdef INFTIM
405                 if (tcp->u_arg[2] == INFTIM)
406                         tprints("INFTIM");
407                 else
408 #endif
409                         tprintf("%ld", tcp->u_arg[2]);
410         }
411         return rc;
412 }
413
414 int
415 sys_ppoll(struct tcb *tcp)
416 {
417         int rc = decode_poll(tcp, tcp->u_arg[2]);
418         if (entering(tcp)) {
419                 print_timespec(tcp, tcp->u_arg[2]);
420                 tprints(", ");
421                 print_sigset(tcp, tcp->u_arg[3], 0);
422                 tprintf(", %lu", tcp->u_arg[4]);
423         }
424         return rc;
425 }
426
427 #else /* !HAVE_SYS_POLL_H */
428 int
429 sys_poll(struct tcb *tcp)
430 {
431         return 0;
432 }
433 #endif