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