]> granicus.if.org Git - strace/blob - ipc.c
Ensure that SWAP_FLAG_* constants are defined
[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 MIPS && !defined HPPA
182         return 1;
183 #endif
184         return 0;
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         unsigned long raddr;
408
409         if (exiting(tcp)) {
410                 tprintf("%lu", tcp->u_arg[0]);
411                 if (indirect_ipccall(tcp)) {
412                         tprintf(", %#lx", tcp->u_arg[3]);
413                         tprints(", ");
414                         printflags(shm_flags, tcp->u_arg[1], "SHM_???");
415                 } else {
416                         tprintf(", %#lx", tcp->u_arg[1]);
417                         tprints(", ");
418                         printflags(shm_flags, tcp->u_arg[2], "SHM_???");
419                 }
420                 if (syserror(tcp))
421                         return 0;
422 /* HPPA does not use an IPC multiplexer on Linux.  */
423 #if !defined(HPPA)
424                 if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
425                         return RVAL_NONE;
426                 tcp->u_rval = raddr;
427 #endif
428                 return RVAL_HEX;
429         }
430         return 0;
431 }
432
433 int sys_shmdt(struct tcb *tcp)
434 {
435         if (entering(tcp)) {
436                 if (indirect_ipccall(tcp)) {
437                         tprintf("%#lx", tcp->u_arg[3]);
438                 } else {
439                         tprintf("%#lx", tcp->u_arg[0]);
440                 }
441         }
442         return 0;
443 }
444
445 int
446 sys_mq_open(struct tcb *tcp)
447 {
448         if (entering(tcp)) {
449                 printpath(tcp, tcp->u_arg[0]);
450                 tprints(", ");
451                 /* flags */
452                 tprint_open_modes(tcp->u_arg[1]);
453                 if (tcp->u_arg[1] & O_CREAT) {
454 # ifndef HAVE_MQUEUE_H
455                         tprintf(", %lx", tcp->u_arg[2]);
456 # else
457                         struct mq_attr attr;
458                         /* mode */
459                         tprintf(", %#lo, ", tcp->u_arg[2]);
460                         if (umove(tcp, tcp->u_arg[3], &attr) < 0)
461                                 tprints("{ ??? }");
462                         else
463                                 tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
464                                         (long) attr.mq_maxmsg,
465                                         (long) attr.mq_msgsize);
466 # endif
467                 }
468         }
469         return 0;
470 }
471
472 int
473 sys_mq_timedsend(struct tcb *tcp)
474 {
475         if (entering(tcp)) {
476                 tprintf("%ld, ", tcp->u_arg[0]);
477                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
478                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
479                 printtv(tcp, tcp->u_arg[4]);
480         }
481         return 0;
482 }
483
484 int
485 sys_mq_timedreceive(struct tcb *tcp)
486 {
487         if (entering(tcp))
488                 tprintf("%ld, ", tcp->u_arg[0]);
489         else {
490                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
491                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
492                 printtv(tcp, tcp->u_arg[4]);
493         }
494         return 0;
495 }
496
497 int
498 sys_mq_notify(struct tcb *tcp)
499 {
500         if (entering(tcp)) {
501                 tprintf("%ld, ", tcp->u_arg[0]);
502                 printsigevent(tcp, tcp->u_arg[1]);
503         }
504         return 0;
505 }
506
507 static void
508 printmqattr(struct tcb *tcp, long addr)
509 {
510         if (addr == 0)
511                 tprints("NULL");
512         else {
513 # ifndef HAVE_MQUEUE_H
514                 tprintf("%#lx", addr);
515 # else
516                 struct mq_attr attr;
517                 if (umove(tcp, addr, &attr) < 0) {
518                         tprints("{...}");
519                         return;
520                 }
521                 tprints("{mq_flags=");
522                 tprint_open_modes(attr.mq_flags);
523                 tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
524                         (long) attr.mq_maxmsg, (long) attr.mq_msgsize,
525                         (long) attr.mq_curmsgs);
526 # endif
527         }
528 }
529
530 int
531 sys_mq_getsetattr(struct tcb *tcp)
532 {
533         if (entering(tcp)) {
534                 tprintf("%ld, ", tcp->u_arg[0]);
535                 printmqattr(tcp, tcp->u_arg[1]);
536                 tprints(", ");
537         } else
538                 printmqattr(tcp, tcp->u_arg[2]);
539         return 0;
540 }
541
542 int
543 sys_ipc(struct tcb *tcp)
544 {
545         return printargs(tcp);
546 }