]> granicus.if.org Git - strace/blob - ipc.c
Show more details about signals received by traced processess
[strace] / ipc.c
1 /*
2  * Copyright (c) 1993 Ulrich Pegelow <pegelow@moorea.uni-muenster.de>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  *      $Id$
31  */
32
33 #include "defs.h"
34
35 #if defined(LINUX) || defined(SUNOS4) || defined(FREEBSD)
36
37 # ifdef HAVE_MQUEUE_H
38 #  include <mqueue.h>
39 # endif
40
41 #include <fcntl.h>
42 #include <sys/ipc.h>
43 #include <sys/sem.h>
44 #include <sys/msg.h>
45 #include <sys/shm.h>
46
47 #ifndef MSG_STAT
48 #define MSG_STAT 11
49 #endif
50 #ifndef MSG_INFO
51 #define MSG_INFO 12
52 #endif
53 #ifndef SHM_STAT
54 #define SHM_STAT 13
55 #endif
56 #ifndef SHM_INFO
57 #define SHM_INFO 14
58 #endif
59 #ifndef SEM_STAT
60 #define SEM_STAT 18
61 #endif
62 #ifndef SEM_INFO
63 #define SEM_INFO 19
64 #endif
65
66 #if defined LINUX && !defined IPC_64
67 # define IPC_64 0x100
68 #endif
69
70 extern void printsigevent(struct tcb *tcp, long arg);
71
72 static const struct xlat msgctl_flags[] = {
73         { IPC_RMID,     "IPC_RMID"      },
74         { IPC_SET,      "IPC_SET"       },
75         { IPC_STAT,     "IPC_STAT"      },
76 #ifdef LINUX
77         { IPC_INFO,     "IPC_INFO"      },
78         { MSG_STAT,     "MSG_STAT"      },
79         { MSG_INFO,     "MSG_INFO"      },
80 #endif /* LINUX */
81         { 0,            NULL            },
82 };
83
84 static const struct xlat semctl_flags[] = {
85         { IPC_RMID,     "IPC_RMID"      },
86         { IPC_SET,      "IPC_SET"       },
87         { IPC_STAT,     "IPC_STAT"      },
88 #ifdef LINUX
89         { IPC_INFO,     "IPC_INFO"      },
90         { SEM_STAT,     "SEM_STAT"      },
91         { SEM_INFO,     "SEM_INFO"      },
92 #endif /* LINUX */
93         { GETPID,       "GETPID"        },
94         { GETVAL,       "GETVAL"        },
95         { GETALL,       "GETALL"        },
96         { GETNCNT,      "GETNCNT"       },
97         { GETZCNT,      "GETZCNT"       },
98         { SETVAL,       "SETVAL"        },
99         { SETALL,       "SETALL"        },
100         { 0,            NULL            },
101 };
102
103 static const struct xlat shmctl_flags[] = {
104         { IPC_RMID,     "IPC_RMID"      },
105         { IPC_SET,      "IPC_SET"       },
106         { IPC_STAT,     "IPC_STAT"      },
107 #ifdef LINUX
108         { IPC_INFO,     "IPC_INFO"      },
109         { SHM_STAT,     "SHM_STAT"      },
110         { SHM_INFO,     "SHM_INFO"      },
111 #endif /* LINUX */
112 #ifdef SHM_LOCK
113         { SHM_LOCK,     "SHM_LOCK"      },
114 #endif
115 #ifdef SHM_UNLOCK
116         { SHM_UNLOCK,   "SHM_UNLOCK"    },
117 #endif
118         { 0,            NULL            },
119 };
120
121 static const struct xlat resource_flags[] = {
122         { IPC_CREAT,    "IPC_CREAT"     },
123         { IPC_EXCL,     "IPC_EXCL"      },
124         { IPC_NOWAIT,   "IPC_NOWAIT"    },
125         { 0,            NULL            },
126 };
127
128 static const struct xlat shm_resource_flags[] = {
129         { IPC_CREAT,    "IPC_CREAT"     },
130         { IPC_EXCL,     "IPC_EXCL"      },
131 #ifdef SHM_HUGETLB
132         { SHM_HUGETLB,  "SHM_HUGETLB"   },
133 #endif
134         { 0,            NULL            },
135 };
136
137 static const struct xlat shm_flags[] = {
138 #ifdef LINUX
139         { SHM_REMAP,    "SHM_REMAP"     },
140 #endif /* LINUX */
141         { SHM_RDONLY,   "SHM_RDONLY"    },
142         { SHM_RND,      "SHM_RND"       },
143         { 0,            NULL            },
144 };
145
146 static const struct xlat msg_flags[] = {
147         { MSG_NOERROR,  "MSG_NOERROR"   },
148 #ifdef LINUX
149         { MSG_EXCEPT,   "MSG_EXCEPT"    },
150 #endif /* LINUX */
151         { IPC_NOWAIT,   "IPC_NOWAIT"    },
152         { 0,            NULL            },
153 };
154
155 static const struct xlat semop_flags[] = {
156         { SEM_UNDO,     "SEM_UNDO"      },
157         { IPC_NOWAIT,   "IPC_NOWAIT"    },
158         { 0,            NULL            },
159 };
160
161 int sys_msgget(tcp)
162 struct tcb *tcp;
163 {
164         if (entering(tcp)) {
165                 if (tcp->u_arg[0])
166                         tprintf("%#lx", tcp->u_arg[0]);
167                 else
168                         tprintf("IPC_PRIVATE");
169                 tprintf(", ");
170                 if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
171                         tprintf("|");
172                 tprintf("%#lo", tcp->u_arg[1] & 0777);
173         }
174         return 0;
175 }
176
177 #ifdef IPC_64
178 # define PRINTCTL(flagset, arg, dflt) \
179         if ((arg) & IPC_64) tprintf("IPC_64|"); \
180         printxval((flagset), (arg) &~ IPC_64, dflt)
181 #else
182 # define PRINTCTL printxval
183 #endif
184
185 static int
186 indirect_ipccall(tcp)
187 struct tcb *tcp;
188 {
189 #ifdef LINUX
190 #ifdef X86_64
191         return current_personality > 0;
192 #endif
193 #if defined IA64
194         return tcp->scno < 1024; /* ia32 emulation syscalls are low */
195 #endif
196 #if !defined MIPS && !defined HPPA
197         return 1;
198 #endif
199 #endif  /* LINUX */
200         return 0;
201 }
202
203 int sys_msgctl(tcp)
204 struct tcb *tcp;
205 {
206         if (entering(tcp)) {
207                 tprintf("%lu, ", tcp->u_arg[0]);
208                 PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
209                 tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
210         }
211         return 0;
212 }
213
214 static void
215 tprint_msgsnd(struct tcb *tcp, long addr, unsigned long count,
216               unsigned long flags)
217 {
218         long mtype;
219
220         if (umove(tcp, addr, &mtype) < 0) {
221                 tprintf("%#lx", addr);
222         } else {
223                 tprintf("{%lu, ", mtype);
224                 printstr(tcp, addr + sizeof(mtype), count);
225                 tprintf("}");
226         }
227         tprintf(", %lu, ", count);
228         printflags(msg_flags, flags, "MSG_???");
229 }
230
231 int sys_msgsnd(struct tcb *tcp)
232 {
233         if (entering(tcp)) {
234                 tprintf("%d, ", (int) tcp->u_arg[0]);
235                 if (indirect_ipccall(tcp)) {
236                         tprint_msgsnd(tcp, tcp->u_arg[3], tcp->u_arg[1],
237                                       tcp->u_arg[2]);
238                 } else {
239                         tprint_msgsnd(tcp, tcp->u_arg[1], tcp->u_arg[2],
240                                       tcp->u_arg[3]);
241                 }
242         }
243         return 0;
244 }
245
246 static void
247 tprint_msgrcv(struct tcb *tcp, long addr, unsigned long count, long msgtyp)
248 {
249         long mtype;
250
251         if (syserror(tcp) || umove(tcp, addr, &mtype) < 0) {
252                 tprintf("%#lx", addr);
253         } else {
254                 tprintf("{%lu, ", mtype);
255                 printstr(tcp, addr + sizeof(mtype), count);
256                 tprintf("}");
257         }
258         tprintf(", %lu, %ld, ", count, msgtyp);
259 }
260
261 int sys_msgrcv(struct tcb *tcp)
262 {
263         if (entering(tcp)) {
264                 tprintf("%d, ", (int) tcp->u_arg[0]);
265         } else {
266                 if (indirect_ipccall(tcp)) {
267                         struct ipc_wrapper {
268                                 struct msgbuf *msgp;
269                                 long msgtyp;
270                         } tmp;
271
272                         if (umove(tcp, tcp->u_arg[3], &tmp) < 0) {
273                                 tprintf("%#lx, %lu, ",
274                                         tcp->u_arg[3], tcp->u_arg[1]);
275                         } else {
276                                 tprint_msgrcv(tcp, (long) tmp.msgp,
277                                         tcp->u_arg[1], tmp.msgtyp);
278                         }
279                         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
280                 } else {
281                         tprint_msgrcv(tcp, tcp->u_arg[1],
282                                 tcp->u_arg[2], tcp->u_arg[3]);
283                         printflags(msg_flags, tcp->u_arg[4], "MSG_???");
284                 }
285         }
286         return 0;
287 }
288
289 static void
290 tprint_sembuf(struct tcb *tcp, long addr, unsigned long count)
291 {
292         unsigned long i, max_count;
293
294         if (abbrev(tcp))
295                 max_count = (max_strlen < count) ? max_strlen : count;
296         else
297                 max_count = count;
298
299         if (!max_count) {
300                 tprintf("%#lx, %lu", addr, count);
301                 return;
302         }
303
304         for(i = 0; i < max_count; ++i) {
305                 struct sembuf sb;
306                 if (i)
307                         tprintf(", ");
308                 if (umove(tcp, addr + i * sizeof(struct sembuf), &sb) < 0) {
309                         if (i) {
310                                 tprintf("{???}");
311                                 break;
312                         } else {
313                                 tprintf("%#lx, %lu", addr, count);
314                                 return;
315                         }
316                 } else {
317                         if (!i)
318                                 tprintf("{");
319                         tprintf("{%u, %d, ", sb.sem_num, sb.sem_op);
320                         printflags(semop_flags, sb.sem_flg, "SEM_???");
321                         tprintf("}");
322                 }
323         }
324
325         if (i < max_count || max_count < count)
326                 tprintf(", ...");
327
328         tprintf("}, %lu", count);
329 }
330
331 int sys_semop(struct tcb *tcp)
332 {
333         if (entering(tcp)) {
334                 tprintf("%lu, ", tcp->u_arg[0]);
335                 if (indirect_ipccall(tcp)) {
336                         tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
337                 } else {
338                         tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
339                 }
340         }
341         return 0;
342 }
343
344 #ifdef LINUX
345 int sys_semtimedop(struct tcb *tcp)
346 {
347         if (entering(tcp)) {
348                 tprintf("%lu, ", tcp->u_arg[0]);
349                 if (indirect_ipccall(tcp)) {
350                         tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
351                         tprintf(", ");
352                         printtv(tcp, tcp->u_arg[5]);
353                 } else {
354                         tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
355                         tprintf(", ");
356                         printtv(tcp, tcp->u_arg[3]);
357                 }
358         }
359         return 0;
360 }
361 #endif
362
363 int sys_semget(tcp)
364 struct tcb *tcp;
365 {
366         if (entering(tcp)) {
367                 if (tcp->u_arg[0])
368                         tprintf("%#lx", tcp->u_arg[0]);
369                 else
370                         tprintf("IPC_PRIVATE");
371                 tprintf(", %lu", tcp->u_arg[1]);
372                 tprintf(", ");
373                 if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
374                         tprintf("|");
375                 tprintf("%#lo", tcp->u_arg[2] & 0777);
376         }
377         return 0;
378 }
379
380 int sys_semctl(tcp)
381 struct tcb *tcp;
382 {
383         if (entering(tcp)) {
384                 tprintf("%lu", tcp->u_arg[0]);
385                 tprintf(", %lu, ", tcp->u_arg[1]);
386                 PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
387                 tprintf(", %#lx", tcp->u_arg[3]);
388         }
389         return 0;
390 }
391
392 int sys_shmget(tcp)
393 struct tcb *tcp;
394 {
395         if (entering(tcp)) {
396                 if (tcp->u_arg[0])
397                         tprintf("%#lx", tcp->u_arg[0]);
398                 else
399                         tprintf("IPC_PRIVATE");
400                 tprintf(", %lu", tcp->u_arg[1]);
401                 tprintf(", ");
402                 if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
403                         tprintf("|");
404                 tprintf("%#lo", tcp->u_arg[2] & 0777);
405         }
406         return 0;
407 }
408
409 int sys_shmctl(tcp)
410 struct tcb *tcp;
411 {
412         if (entering(tcp)) {
413                 tprintf("%lu, ", tcp->u_arg[0]);
414                 PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
415                 if (indirect_ipccall(tcp)) {
416                         tprintf(", %#lx", tcp->u_arg[3]);
417                 } else {
418                         tprintf(", %#lx", tcp->u_arg[2]);
419                 }
420         }
421         return 0;
422 }
423
424 int sys_shmat(tcp)
425 struct tcb *tcp;
426 {
427 #ifdef LINUX
428         unsigned long raddr;
429 #endif /* LINUX */
430
431         if (exiting(tcp)) {
432                 tprintf("%lu", tcp->u_arg[0]);
433                 if (indirect_ipccall(tcp)) {
434                         tprintf(", %#lx", tcp->u_arg[3]);
435                         tprintf(", ");
436                         printflags(shm_flags, tcp->u_arg[1], "SHM_???");
437                 } else {
438                         tprintf(", %#lx", tcp->u_arg[1]);
439                         tprintf(", ");
440                         printflags(shm_flags, tcp->u_arg[2], "SHM_???");
441                 }
442                 if (syserror(tcp))
443                         return 0;
444 /* HPPA does not use an IPC multiplexer on Linux.  */
445 #if defined(LINUX) && !defined(HPPA)
446                 if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
447                         return RVAL_NONE;
448                 tcp->u_rval = raddr;
449 #endif /* LINUX */
450                 return RVAL_HEX;
451         }
452         return 0;
453 }
454
455 int sys_shmdt(tcp)
456 struct tcb *tcp;
457 {
458         if (entering(tcp)) {
459                 if (indirect_ipccall(tcp)) {
460                         tprintf("%#lx", tcp->u_arg[3]);
461                 } else {
462                         tprintf("%#lx", tcp->u_arg[0]);
463                 }
464         }
465         return 0;
466 }
467
468 #endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
469
470 #ifdef LINUX
471 int
472 sys_mq_open(struct tcb *tcp)
473 {
474         if (entering(tcp)) {
475                 printpath(tcp, tcp->u_arg[0]);
476                 tprintf(", ");
477                 /* flags */
478                 tprint_open_modes(tcp->u_arg[1]);
479                 if (tcp->u_arg[1] & O_CREAT) {
480 # ifndef HAVE_MQUEUE_H
481                         tprintf(", %lx", tcp->u_arg[2]);
482 # else
483                         struct mq_attr attr;
484                         /* mode */
485                         tprintf(", %#lo, ", tcp->u_arg[2]);
486                         if (umove(tcp, tcp->u_arg[3], &attr) < 0)
487                                 tprintf("{ ??? }");
488                         else
489                                 tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
490                                         attr.mq_maxmsg, attr.mq_msgsize);
491 # endif
492                 }
493         }
494         return 0;
495 }
496
497 int
498 sys_mq_timedsend(struct tcb *tcp)
499 {
500         if (entering(tcp)) {
501                 tprintf("%ld, ", tcp->u_arg[0]);
502                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
503                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
504                 printtv(tcp, tcp->u_arg[4]);
505         }
506         return 0;
507 }
508
509 int
510 sys_mq_timedreceive(struct tcb *tcp)
511 {
512         if (entering(tcp))
513                 tprintf("%ld, ", tcp->u_arg[0]);
514         else {
515                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
516                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
517                 printtv(tcp, tcp->u_arg[4]);
518         }
519         return 0;
520 }
521
522 int
523 sys_mq_notify(struct tcb *tcp)
524 {
525         if (entering(tcp)) {
526                 tprintf("%ld, ", tcp->u_arg[0]);
527                 printsigevent(tcp, tcp->u_arg[1]);
528         }
529         return 0;
530 }
531
532 static void
533 printmqattr(struct tcb *tcp, long addr)
534 {
535         if (addr == 0)
536                 tprintf("NULL");
537         else {
538 # ifndef HAVE_MQUEUE_H
539                 tprintf("%#lx", addr);
540 # else
541                 struct mq_attr attr;
542                 if (umove(tcp, addr, &attr) < 0) {
543                         tprintf("{...}");
544                         return;
545                 }
546                 tprintf("{mq_flags=");
547                 tprint_open_modes(attr.mq_flags);
548                 tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
549                         attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
550 # endif
551         }
552 }
553
554 int
555 sys_mq_getsetattr(struct tcb *tcp)
556 {
557         if (entering(tcp)) {
558                 tprintf("%ld, ", tcp->u_arg[0]);
559                 printmqattr(tcp, tcp->u_arg[1]);
560                 tprintf(", ");
561         } else
562                 printmqattr(tcp, tcp->u_arg[2]);
563         return 0;
564 }
565 #endif