]> granicus.if.org Git - strace/blob - ipc.c
00dc9461c5107e3364202c0dc98e470b9a08881c
[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 # ifdef HAVE_MQUEUE_H
36 #  include <mqueue.h>
37 # endif
38
39 #include <fcntl.h>
40 #include <sys/ipc.h>
41 #include <sys/sem.h>
42 #include <sys/msg.h>
43 #include <sys/shm.h>
44
45 #ifndef MSG_STAT
46 #define MSG_STAT 11
47 #endif
48 #ifndef MSG_INFO
49 #define MSG_INFO 12
50 #endif
51 #ifndef SHM_STAT
52 #define SHM_STAT 13
53 #endif
54 #ifndef SHM_INFO
55 #define SHM_INFO 14
56 #endif
57 #ifndef SEM_STAT
58 #define SEM_STAT 18
59 #endif
60 #ifndef SEM_INFO
61 #define SEM_INFO 19
62 #endif
63
64 #if !defined IPC_64
65 # define IPC_64 0x100
66 #endif
67
68 extern void printsigevent(struct tcb *tcp, long arg);
69
70 static const struct xlat msgctl_flags[] = {
71         { IPC_RMID,     "IPC_RMID"      },
72         { IPC_SET,      "IPC_SET"       },
73         { IPC_STAT,     "IPC_STAT"      },
74         { IPC_INFO,     "IPC_INFO"      },
75         { MSG_STAT,     "MSG_STAT"      },
76         { MSG_INFO,     "MSG_INFO"      },
77         { 0,            NULL            },
78 };
79
80 static const struct xlat semctl_flags[] = {
81         { IPC_RMID,     "IPC_RMID"      },
82         { IPC_SET,      "IPC_SET"       },
83         { IPC_STAT,     "IPC_STAT"      },
84         { IPC_INFO,     "IPC_INFO"      },
85         { SEM_STAT,     "SEM_STAT"      },
86         { SEM_INFO,     "SEM_INFO"      },
87         { GETPID,       "GETPID"        },
88         { GETVAL,       "GETVAL"        },
89         { GETALL,       "GETALL"        },
90         { GETNCNT,      "GETNCNT"       },
91         { GETZCNT,      "GETZCNT"       },
92         { SETVAL,       "SETVAL"        },
93         { SETALL,       "SETALL"        },
94         { 0,            NULL            },
95 };
96
97 static const struct xlat shmctl_flags[] = {
98         { IPC_RMID,     "IPC_RMID"      },
99         { IPC_SET,      "IPC_SET"       },
100         { IPC_STAT,     "IPC_STAT"      },
101         { IPC_INFO,     "IPC_INFO"      },
102         { SHM_STAT,     "SHM_STAT"      },
103         { SHM_INFO,     "SHM_INFO"      },
104 #ifdef SHM_LOCK
105         { SHM_LOCK,     "SHM_LOCK"      },
106 #endif
107 #ifdef SHM_UNLOCK
108         { SHM_UNLOCK,   "SHM_UNLOCK"    },
109 #endif
110         { 0,            NULL            },
111 };
112
113 static const struct xlat resource_flags[] = {
114         { IPC_CREAT,    "IPC_CREAT"     },
115         { IPC_EXCL,     "IPC_EXCL"      },
116         { IPC_NOWAIT,   "IPC_NOWAIT"    },
117         { 0,            NULL            },
118 };
119
120 static const struct xlat shm_resource_flags[] = {
121         { IPC_CREAT,    "IPC_CREAT"     },
122         { IPC_EXCL,     "IPC_EXCL"      },
123 #ifdef SHM_HUGETLB
124         { SHM_HUGETLB,  "SHM_HUGETLB"   },
125 #endif
126         { 0,            NULL            },
127 };
128
129 static const struct xlat shm_flags[] = {
130         { SHM_REMAP,    "SHM_REMAP"     },
131         { SHM_RDONLY,   "SHM_RDONLY"    },
132         { SHM_RND,      "SHM_RND"       },
133         { 0,            NULL            },
134 };
135
136 static const struct xlat msg_flags[] = {
137         { MSG_NOERROR,  "MSG_NOERROR"   },
138         { MSG_EXCEPT,   "MSG_EXCEPT"    },
139         { IPC_NOWAIT,   "IPC_NOWAIT"    },
140         { 0,            NULL            },
141 };
142
143 static const struct xlat semop_flags[] = {
144         { SEM_UNDO,     "SEM_UNDO"      },
145         { IPC_NOWAIT,   "IPC_NOWAIT"    },
146         { 0,            NULL            },
147 };
148
149 int sys_msgget(struct tcb *tcp)
150 {
151         if (entering(tcp)) {
152                 if (tcp->u_arg[0])
153                         tprintf("%#lx", tcp->u_arg[0]);
154                 else
155                         tprints("IPC_PRIVATE");
156                 tprints(", ");
157                 if (printflags(resource_flags, tcp->u_arg[1] & ~0777, NULL) != 0)
158                         tprints("|");
159                 tprintf("%#lo", tcp->u_arg[1] & 0777);
160         }
161         return 0;
162 }
163
164 #ifdef IPC_64
165 # define PRINTCTL(flagset, arg, dflt) \
166         if ((arg) & IPC_64) tprints("IPC_64|"); \
167         printxval((flagset), (arg) &~ IPC_64, dflt)
168 #else
169 # define PRINTCTL printxval
170 #endif
171
172 static int
173 indirect_ipccall(struct tcb *tcp)
174 {
175 #ifdef X86_64
176         return current_personality > 0;
177 #endif
178 #if defined IA64
179         return tcp->scno < 1024; /* ia32 emulation syscalls are low */
180 #endif
181 #if defined(ALPHA) || defined(MIPS) || defined(HPPA) || defined(__ARM_EABI__)
182         return 0;
183 #endif
184         return 1;
185 }
186
187 int sys_msgctl(struct tcb *tcp)
188 {
189         if (entering(tcp)) {
190                 tprintf("%lu, ", tcp->u_arg[0]);
191                 PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
192                 tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
193         }
194         return 0;
195 }
196
197 static void
198 tprint_msgsnd(struct tcb *tcp, long addr, unsigned long count,
199               unsigned long flags)
200 {
201         long mtype;
202
203         if (umove(tcp, addr, &mtype) < 0) {
204                 tprintf("%#lx", addr);
205         } else {
206                 tprintf("{%lu, ", mtype);
207                 printstr(tcp, addr + sizeof(mtype), count);
208                 tprints("}");
209         }
210         tprintf(", %lu, ", count);
211         printflags(msg_flags, flags, "MSG_???");
212 }
213
214 int sys_msgsnd(struct tcb *tcp)
215 {
216         if (entering(tcp)) {
217                 tprintf("%d, ", (int) tcp->u_arg[0]);
218                 if (indirect_ipccall(tcp)) {
219                         tprint_msgsnd(tcp, tcp->u_arg[3], tcp->u_arg[1],
220                                       tcp->u_arg[2]);
221                 } else {
222                         tprint_msgsnd(tcp, tcp->u_arg[1], tcp->u_arg[2],
223                                       tcp->u_arg[3]);
224                 }
225         }
226         return 0;
227 }
228
229 static void
230 tprint_msgrcv(struct tcb *tcp, long addr, unsigned long count, long msgtyp)
231 {
232         long mtype;
233
234         if (syserror(tcp) || umove(tcp, addr, &mtype) < 0) {
235                 tprintf("%#lx", addr);
236         } else {
237                 tprintf("{%lu, ", mtype);
238                 printstr(tcp, addr + sizeof(mtype), count);
239                 tprints("}");
240         }
241         tprintf(", %lu, %ld, ", count, msgtyp);
242 }
243
244 int sys_msgrcv(struct tcb *tcp)
245 {
246         if (entering(tcp)) {
247                 tprintf("%d, ", (int) tcp->u_arg[0]);
248         } else {
249                 if (indirect_ipccall(tcp)) {
250                         struct ipc_wrapper {
251                                 struct msgbuf *msgp;
252                                 long msgtyp;
253                         } tmp;
254
255                         if (umove(tcp, tcp->u_arg[3], &tmp) < 0) {
256                                 tprintf("%#lx, %lu, ",
257                                         tcp->u_arg[3], tcp->u_arg[1]);
258                         } else {
259                                 tprint_msgrcv(tcp, (long) tmp.msgp,
260                                         tcp->u_arg[1], tmp.msgtyp);
261                         }
262                         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
263                 } else {
264                         tprint_msgrcv(tcp, tcp->u_arg[1],
265                                 tcp->u_arg[2], tcp->u_arg[3]);
266                         printflags(msg_flags, tcp->u_arg[4], "MSG_???");
267                 }
268         }
269         return 0;
270 }
271
272 static void
273 tprint_sembuf(struct tcb *tcp, long addr, unsigned long count)
274 {
275         unsigned long i, max_count;
276
277         if (abbrev(tcp))
278                 max_count = (max_strlen < count) ? max_strlen : count;
279         else
280                 max_count = count;
281
282         if (!max_count) {
283                 tprintf("%#lx, %lu", addr, count);
284                 return;
285         }
286
287         for (i = 0; i < max_count; ++i) {
288                 struct sembuf sb;
289                 if (i)
290                         tprints(", ");
291                 if (umove(tcp, addr + i * sizeof(struct sembuf), &sb) < 0) {
292                         if (i) {
293                                 tprints("{???}");
294                                 break;
295                         } else {
296                                 tprintf("%#lx, %lu", addr, count);
297                                 return;
298                         }
299                 } else {
300                         if (!i)
301                                 tprints("{");
302                         tprintf("{%u, %d, ", sb.sem_num, sb.sem_op);
303                         printflags(semop_flags, sb.sem_flg, "SEM_???");
304                         tprints("}");
305                 }
306         }
307
308         if (i < max_count || max_count < count)
309                 tprints(", ...");
310
311         tprintf("}, %lu", count);
312 }
313
314 int sys_semop(struct tcb *tcp)
315 {
316         if (entering(tcp)) {
317                 tprintf("%lu, ", tcp->u_arg[0]);
318                 if (indirect_ipccall(tcp)) {
319                         tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
320                 } else {
321                         tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
322                 }
323         }
324         return 0;
325 }
326
327 int sys_semtimedop(struct tcb *tcp)
328 {
329         if (entering(tcp)) {
330                 tprintf("%lu, ", tcp->u_arg[0]);
331                 if (indirect_ipccall(tcp)) {
332                         tprint_sembuf(tcp, tcp->u_arg[3], tcp->u_arg[1]);
333                         tprints(", ");
334 #if defined(S390)
335                         printtv(tcp, tcp->u_arg[2]);
336 #else
337                         printtv(tcp, tcp->u_arg[5]);
338 #endif
339                 } else {
340                         tprint_sembuf(tcp, tcp->u_arg[1], tcp->u_arg[2]);
341                         tprints(", ");
342                         printtv(tcp, tcp->u_arg[3]);
343                 }
344         }
345         return 0;
346 }
347
348 int sys_semget(struct tcb *tcp)
349 {
350         if (entering(tcp)) {
351                 if (tcp->u_arg[0])
352                         tprintf("%#lx", tcp->u_arg[0]);
353                 else
354                         tprints("IPC_PRIVATE");
355                 tprintf(", %lu", tcp->u_arg[1]);
356                 tprints(", ");
357                 if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
358                         tprints("|");
359                 tprintf("%#lo", tcp->u_arg[2] & 0777);
360         }
361         return 0;
362 }
363
364 int sys_semctl(struct tcb *tcp)
365 {
366         if (entering(tcp)) {
367                 tprintf("%lu", tcp->u_arg[0]);
368                 tprintf(", %lu, ", tcp->u_arg[1]);
369                 PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
370                 tprintf(", %#lx", tcp->u_arg[3]);
371         }
372         return 0;
373 }
374
375 int sys_shmget(struct tcb *tcp)
376 {
377         if (entering(tcp)) {
378                 if (tcp->u_arg[0])
379                         tprintf("%#lx", tcp->u_arg[0]);
380                 else
381                         tprints("IPC_PRIVATE");
382                 tprintf(", %lu", tcp->u_arg[1]);
383                 tprints(", ");
384                 if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
385                         tprints("|");
386                 tprintf("%#lo", tcp->u_arg[2] & 0777);
387         }
388         return 0;
389 }
390
391 int sys_shmctl(struct tcb *tcp)
392 {
393         if (entering(tcp)) {
394                 tprintf("%lu, ", tcp->u_arg[0]);
395                 PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
396                 if (indirect_ipccall(tcp)) {
397                         tprintf(", %#lx", tcp->u_arg[3]);
398                 } else {
399                         tprintf(", %#lx", tcp->u_arg[2]);
400                 }
401         }
402         return 0;
403 }
404
405 int sys_shmat(struct tcb *tcp)
406 {
407         if (exiting(tcp)) {
408                 tprintf("%lu", tcp->u_arg[0]);
409                 if (indirect_ipccall(tcp)) {
410                         tprintf(", %#lx", tcp->u_arg[3]);
411                         tprints(", ");
412                         printflags(shm_flags, tcp->u_arg[1], "SHM_???");
413                 } else {
414                         tprintf(", %#lx", tcp->u_arg[1]);
415                         tprints(", ");
416                         printflags(shm_flags, tcp->u_arg[2], "SHM_???");
417                 }
418                 if (syserror(tcp))
419                         return 0;
420                 if (indirect_ipccall(tcp)) {
421                         unsigned long raddr;
422                         if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
423                                 return RVAL_NONE;
424                         tcp->u_rval = raddr;
425                 }
426                 return RVAL_HEX;
427         }
428         return 0;
429 }
430
431 int sys_shmdt(struct tcb *tcp)
432 {
433         if (entering(tcp)) {
434                 if (indirect_ipccall(tcp)) {
435                         tprintf("%#lx", tcp->u_arg[3]);
436                 } else {
437                         tprintf("%#lx", tcp->u_arg[0]);
438                 }
439         }
440         return 0;
441 }
442
443 int
444 sys_mq_open(struct tcb *tcp)
445 {
446         if (entering(tcp)) {
447                 printpath(tcp, tcp->u_arg[0]);
448                 tprints(", ");
449                 /* flags */
450                 tprint_open_modes(tcp->u_arg[1]);
451                 if (tcp->u_arg[1] & O_CREAT) {
452 # ifndef HAVE_MQUEUE_H
453                         tprintf(", %lx", tcp->u_arg[2]);
454 # else
455                         struct mq_attr attr;
456                         /* mode */
457                         tprintf(", %#lo, ", tcp->u_arg[2]);
458                         if (umove(tcp, tcp->u_arg[3], &attr) < 0)
459                                 tprints("{ ??? }");
460                         else
461                                 tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
462                                         (long) attr.mq_maxmsg,
463                                         (long) attr.mq_msgsize);
464 # endif
465                 }
466         }
467         return 0;
468 }
469
470 int
471 sys_mq_timedsend(struct tcb *tcp)
472 {
473         if (entering(tcp)) {
474                 tprintf("%ld, ", tcp->u_arg[0]);
475                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
476                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
477                 printtv(tcp, tcp->u_arg[4]);
478         }
479         return 0;
480 }
481
482 int
483 sys_mq_timedreceive(struct tcb *tcp)
484 {
485         if (entering(tcp))
486                 tprintf("%ld, ", tcp->u_arg[0]);
487         else {
488                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
489                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
490                 printtv(tcp, tcp->u_arg[4]);
491         }
492         return 0;
493 }
494
495 int
496 sys_mq_notify(struct tcb *tcp)
497 {
498         if (entering(tcp)) {
499                 tprintf("%ld, ", tcp->u_arg[0]);
500                 printsigevent(tcp, tcp->u_arg[1]);
501         }
502         return 0;
503 }
504
505 static void
506 printmqattr(struct tcb *tcp, long addr)
507 {
508         if (addr == 0)
509                 tprints("NULL");
510         else {
511 # ifndef HAVE_MQUEUE_H
512                 tprintf("%#lx", addr);
513 # else
514                 struct mq_attr attr;
515                 if (umove(tcp, addr, &attr) < 0) {
516                         tprints("{...}");
517                         return;
518                 }
519                 tprints("{mq_flags=");
520                 tprint_open_modes(attr.mq_flags);
521                 tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
522                         (long) attr.mq_maxmsg, (long) attr.mq_msgsize,
523                         (long) attr.mq_curmsgs);
524 # endif
525         }
526 }
527
528 int
529 sys_mq_getsetattr(struct tcb *tcp)
530 {
531         if (entering(tcp)) {
532                 tprintf("%ld, ", tcp->u_arg[0]);
533                 printmqattr(tcp, tcp->u_arg[1]);
534                 tprints(", ");
535         } else
536                 printmqattr(tcp, tcp->u_arg[2]);
537         return 0;
538 }
539
540 int
541 sys_ipc(struct tcb *tcp)
542 {
543         return printargs(tcp);
544 }