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