]> granicus.if.org Git - strace/blob - ipc.c
baec4240de97c63525455cd26ae162d22a0dbe34
[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         return 0;
192 }
193
194 int sys_msgctl(tcp)
195 struct tcb *tcp;
196 {
197         if (entering(tcp)) {
198                 tprintf("%lu, ", tcp->u_arg[0]);
199                 PRINTCTL(msgctl_flags, tcp->u_arg[1], "MSG_???");
200                 tprintf(", %#lx", tcp->u_arg[indirect_ipccall(tcp) ? 3 : 2]);
201         }
202         return 0;
203 }
204
205 int sys_msgsnd(tcp)
206 struct tcb *tcp;
207 {
208         long mtype;
209
210         if (entering(tcp)) {
211                 tprintf("%lu", tcp->u_arg[0]);
212                 if (indirect_ipccall(tcp)) {
213                         umove(tcp, tcp->u_arg[3], &mtype);
214                         tprintf(", {%lu, ", mtype);
215                         printstr(tcp, tcp->u_arg[3] + sizeof(long),
216                                  tcp->u_arg[1]);
217                         tprintf("}, %lu", tcp->u_arg[1]);
218                         tprintf(", ");
219                         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
220                 } else {
221                         umove(tcp, tcp->u_arg[1], &mtype);
222                         tprintf(", {%lu, ", mtype);
223                         printstr(tcp, tcp->u_arg[1] + sizeof(long),
224                                  tcp->u_arg[2]);
225                         tprintf("}, %lu", tcp->u_arg[2]);
226                         tprintf(", ");
227                         printflags(msg_flags, tcp->u_arg[3], "MSG_???");
228                 }
229         }
230         return 0;
231 }
232
233 int sys_msgrcv(tcp)
234 struct tcb *tcp;
235 {
236         long mtype;
237
238         if (entering(tcp)) {
239                 tprintf("%lu, ", tcp->u_arg[0]);
240         } else {
241                 tprintf("%lu", tcp->u_arg[0]);
242                 if (indirect_ipccall(tcp)) {
243                         struct ipc_wrapper {
244                                 struct msgbuf *msgp;
245                                 long msgtyp;
246                         } tmp;
247                         umove(tcp, tcp->u_arg[3], &tmp);
248                         umove(tcp, (long) tmp.msgp, &mtype);
249                         tprintf(", {%lu, ", mtype);
250                         printstr(tcp, (long) (tmp.msgp) + sizeof(long),
251                                  tcp->u_arg[1]);
252                         tprintf("}, %lu", tcp->u_arg[1]);
253                         tprintf(", %ld", tmp.msgtyp);
254                         tprintf(", ");
255                         printflags(msg_flags, tcp->u_arg[2], "MSG_???");
256                 } else {
257                         umove(tcp, tcp->u_arg[1], &mtype);
258                         tprintf("{%lu, ", mtype);
259                         printstr(tcp, tcp->u_arg[1] + sizeof(long),
260                                  tcp->u_arg[2]);
261                         tprintf("}, %lu", tcp->u_arg[2]);
262                         tprintf(", %ld", tcp->u_arg[3]);
263                         tprintf(", ");
264                         printflags(msg_flags, tcp->u_arg[4], "MSG_???");
265                 }
266         }
267         return 0;
268 }
269
270 int sys_semop(tcp)
271 struct tcb *tcp;
272 {
273         if (entering(tcp)) {
274                 tprintf("%lu", tcp->u_arg[0]);
275                 if (indirect_ipccall(tcp)) {
276                         tprintf(", %#lx", tcp->u_arg[3]);
277                         tprintf(", %lu", tcp->u_arg[1]);
278                 } else {
279                         tprintf(", %#lx", tcp->u_arg[1]);
280                         tprintf(", %lu", tcp->u_arg[2]);
281                 }
282         }
283         return 0;
284 }
285
286 #ifdef LINUX
287 int sys_semtimedop(tcp)
288 struct tcb *tcp;
289 {
290         if (entering(tcp)) {
291                 tprintf("%lu", tcp->u_arg[0]);
292                 if (!indirect_ipccall(tcp)) {
293                         tprintf(", %#lx", tcp->u_arg[3]);
294                         tprintf(", %lu, ", tcp->u_arg[1]);
295                         printtv(tcp, tcp->u_arg[5]);
296                 } else {
297                         tprintf(", %#lx", tcp->u_arg[1]);
298                         tprintf(", %lu, ", tcp->u_arg[2]);
299                         printtv(tcp, tcp->u_arg[3]);
300                 }
301         }
302         return 0;
303 }
304 #endif
305
306 int sys_semget(tcp)
307 struct tcb *tcp;
308 {
309         if (entering(tcp)) {
310                 if (tcp->u_arg[0])
311                         tprintf("%lu", tcp->u_arg[0]);
312                 else
313                         tprintf("IPC_PRIVATE");
314                 tprintf(", %lu", tcp->u_arg[1]);
315                 tprintf(", ");
316                 if (printflags(resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
317                         tprintf("|");
318                 tprintf("%#lo", tcp->u_arg[2] & 0777);
319         }
320         return 0;
321 }
322
323 int sys_semctl(tcp)
324 struct tcb *tcp;
325 {
326         if (entering(tcp)) {
327                 tprintf("%lu", tcp->u_arg[0]);
328                 tprintf(", %lu, ", tcp->u_arg[1]);
329                 PRINTCTL(semctl_flags, tcp->u_arg[2], "SEM_???");
330                 tprintf(", %#lx", tcp->u_arg[3]);
331         }
332         return 0;
333 }
334
335 int sys_shmget(tcp)
336 struct tcb *tcp;
337 {
338         if (entering(tcp)) {
339                 if (tcp->u_arg[0])
340                         tprintf("%lu", tcp->u_arg[0]);
341                 else
342                         tprintf("IPC_PRIVATE");
343                 tprintf(", %lu", tcp->u_arg[1]);
344                 tprintf(", ");
345                 if (printflags(shm_resource_flags, tcp->u_arg[2] & ~0777, NULL) != 0)
346                         tprintf("|");
347                 tprintf("%#lo", tcp->u_arg[2] & 0777);
348         }
349         return 0;
350 }
351
352 int sys_shmctl(tcp)
353 struct tcb *tcp;
354 {
355         if (entering(tcp)) {
356                 tprintf("%lu, ", tcp->u_arg[0]);
357                 PRINTCTL(shmctl_flags, tcp->u_arg[1], "SHM_???");
358                 if (indirect_ipccall(tcp)) {
359                         tprintf(", %#lx", tcp->u_arg[3]);
360                 } else {
361                         tprintf(", %#lx", tcp->u_arg[2]);
362                 }
363         }
364         return 0;
365 }
366
367 int sys_shmat(tcp)
368 struct tcb *tcp;
369 {
370 #ifdef LINUX
371         unsigned long raddr;
372 #endif /* LINUX */
373
374         if (exiting(tcp)) {
375                 tprintf("%lu", tcp->u_arg[0]);
376                 if (indirect_ipccall(tcp)) {
377                         tprintf(", %#lx", tcp->u_arg[3]);
378                         tprintf(", ");
379                         printflags(shm_flags, tcp->u_arg[1], "SHM_???");
380                 } else {
381                         tprintf(", %#lx", tcp->u_arg[1]);
382                         tprintf(", ");
383                         printflags(shm_flags, tcp->u_arg[2], "SHM_???");
384                 }
385                 if (syserror(tcp))
386                         return 0;
387 #ifdef LINUX
388                 if (umove(tcp, tcp->u_arg[2], &raddr) < 0)
389                         return RVAL_NONE;
390                 tcp->u_rval = raddr;
391 #endif /* LINUX */
392                 return RVAL_HEX;
393         }
394         return 0;
395 }
396
397 int sys_shmdt(tcp)
398 struct tcb *tcp;
399 {
400         if (entering(tcp)) {
401                 if (indirect_ipccall(tcp)) {
402                         tprintf("%#lx", tcp->u_arg[3]);
403                 } else {
404                         tprintf("%#lx", tcp->u_arg[0]);
405                 }
406         }
407         return 0;
408 }
409
410 #endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
411
412 #ifdef LINUX
413 int sys_mq_open(tcp)
414 struct tcb *tcp;
415 {
416         if (entering(tcp)) {
417                 printpath(tcp, tcp->u_arg[0]);
418                 tprintf(", ");
419                 /* flags */
420                 printflags(openmodes, tcp->u_arg[1] + 1, "O_???");
421                 if (tcp->u_arg[1] & O_CREAT) {
422 # ifndef HAVE_MQUEUE_H
423                         tprintf(", %lx", tcp->u_arg[2]);
424 # else
425                         struct mq_attr attr;
426                         /* mode */
427                         tprintf(", %#lo, ", tcp->u_arg[2]);
428                         if (umove(tcp, tcp->u_arg[3], &attr) < 0)
429                                 tprintf("{ ??? }");
430                         else
431                                 tprintf("{mq_maxmsg=%ld, mq_msgsize=%ld}",
432                                         attr.mq_maxmsg, attr.mq_msgsize);
433 # endif
434                 }
435         }
436         return 0;
437 }
438
439 int sys_mq_timedsend(tcp)
440 struct tcb *tcp;
441 {
442         if (entering(tcp)) {
443                 tprintf("%ld, ", tcp->u_arg[0]);
444                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
445                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
446                 printtv(tcp, tcp->u_arg[4]);
447         }
448         return 0;
449 }
450
451 int sys_mq_timedreceive(tcp)
452 struct tcb *tcp;
453 {
454         if (entering(tcp))
455                 tprintf("%ld, ", tcp->u_arg[0]);
456         else {
457                 printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
458                 tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
459                 printtv(tcp, tcp->u_arg[4]);
460         }
461         return 0;
462 }
463
464 int sys_mq_notify(tcp)
465 struct tcb *tcp;
466 {
467         if (entering(tcp)) {
468                 tprintf("%ld, ", tcp->u_arg[0]);
469                 printsigevent(tcp, tcp->u_arg[1]);
470         }
471         return 0;
472 }
473
474 static void printmqattr(tcp, addr)
475 struct tcb *tcp;
476 long addr;
477 {
478         if (addr == 0)
479                 tprintf("NULL");
480         else {
481 # ifndef HAVE_MQUEUE_H
482                 tprintf("%#lx", addr);
483 # else
484                 struct mq_attr attr;
485                 if (umove(tcp, addr, &attr) < 0) {
486                         tprintf("{...}");
487                         return;
488                 }
489                 tprintf("{mq_flags=");
490                 printflags(openmodes, attr.mq_flags + 1, "O_???");
491                 tprintf(", mq_maxmsg=%ld, mq_msgsize=%ld, mq_curmsg=%ld}",
492                         attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
493 # endif
494         }
495 }
496
497 int sys_mq_getsetattr(tcp)
498 struct tcb *tcp;
499 {
500         if (entering(tcp)) {
501                 tprintf("%ld, ", tcp->u_arg[0]);
502                 printmqattr(tcp, tcp->u_arg[1]);
503                 tprintf(", ");
504         } else
505                 printmqattr(tcp, tcp->u_arg[2]);
506         return 0;
507 }
508 #endif