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