]> granicus.if.org Git - strace/blob - mem.c
Add pollhack
[strace] / mem.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #ifdef LINUX
35 #include <linux/mman.h>
36 #endif
37 #include <sys/mman.h>
38
39 #if defined(LINUX) && defined(__i386__)
40 #include <asm/ldt.h>
41 #endif
42
43 int
44 sys_brk(tcp)
45 struct tcb *tcp;
46 {
47         if (entering(tcp)) {
48                 tprintf("%#lx", tcp->u_arg[0]);
49         }
50 #ifdef LINUX
51         return RVAL_HEX;
52 #else
53         return 0;
54 #endif
55 }
56
57 int
58 sys_sbrk(tcp)
59 struct tcb *tcp;
60 {
61         if (entering(tcp)) {
62                 tprintf("%lu", tcp->u_arg[0]);
63         }
64         return RVAL_HEX;
65 }
66
67 static struct xlat mmap_prot[] = {
68         { PROT_NONE,    "PROT_NONE",    },
69         { PROT_READ,    "PROT_READ"     },
70         { PROT_WRITE,   "PROT_WRITE"    },
71         { PROT_EXEC,    "PROT_EXEC"     },
72         { 0,            NULL            },
73 };
74
75 static struct xlat mmap_flags[] = {
76         { MAP_SHARED,   "MAP_SHARED"    },
77         { MAP_PRIVATE,  "MAP_PRIVATE"   },
78         { MAP_FIXED,    "MAP_FIXED"     },
79 #ifdef MAP_ANONYMOUS
80         { MAP_ANONYMOUS,"MAP_ANONYMOUS" },
81 #endif
82 #ifdef MAP_RENAME
83         { MAP_RENAME,   "MAP_RENAME"    },
84 #endif
85 #ifdef MAP_NORESERVE
86         { MAP_NORESERVE,"MAP_NORESERVE" },
87 #endif
88         /*
89          * XXX - this was introduced in SunOS 4.x to distinguish between
90          * the old pre-4.x "mmap()", which:
91          *
92          *      only let you map devices with an "mmap" routine (e.g.,
93          *      frame buffers) in;
94          *
95          *      required you to specify the mapping address;
96          *
97          *      returned 0 on success and -1 on failure;
98          *
99          * memory and which, and the 4.x "mmap()" which:
100          *
101          *      can map plain files;
102          *
103          *      can be asked to pick where to map the file;
104          *
105          *      returns the address where it mapped the file on success
106          *      and -1 on failure.
107          *
108          * It's not actually used in source code that calls "mmap()"; the
109          * "mmap()" routine adds it for you.
110          *
111          * It'd be nice to come up with some way of eliminating it from
112          * the flags, e.g. reporting calls *without* it as "old_mmap()"
113          * and calls with it as "mmap()".
114          */
115 #ifdef _MAP_NEW
116         { _MAP_NEW,     "_MAP_NEW"      },
117 #endif
118 #ifdef MAP_GROWSDOWN
119         { MAP_GROWSDOWN,"MAP_GROWSDOWN" },
120 #endif
121 #ifdef MAP_DENYWRITE
122         { MAP_DENYWRITE,"MAP_DENYWRITE" },
123 #endif
124 #ifdef MAP_EXECUTABLE
125         { MAP_EXECUTABLE,"MAP_EXECUTABLE"},
126 #endif
127 #ifdef MAP_INHERIT
128         { MAP_INHERIT,"MAP_INHERIT"     },
129 #endif
130 #ifdef MAP_FILE
131         { MAP_FILE,"MAP_FILE"},
132 #endif
133 #ifdef MAP_LOCKED
134         { MAP_LOCKED,"MAP_LOCKED"},
135 #endif
136         { 0,            NULL            },
137 };
138
139 int
140 sys_mmap(tcp)
141 struct tcb *tcp;
142 {
143 #ifdef LINUX
144 #  if defined(ALPHA) || defined(sparc) || defined(POWERPC) || defined(MIPS)
145         long *u_arg = tcp->u_arg;
146 #  else /* !ALPHA */
147         long u_arg[6];
148 #  endif /* !ALPHA */
149 #else /* !LINUX */
150         long *u_arg = tcp->u_arg;
151 #endif /* !LINUX */
152
153         if (entering(tcp)) {
154 #if defined(LINUX) && !defined(ALPHA) && !defined(sparc) && !defined(POWERPC) && !defined(MIPS)
155                 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
156                                 (char *) u_arg) == -1)
157                         return 0;
158 #endif /* LINUX && !ALPHA && !sparc && !POWERPC */
159
160                 /* addr */
161                 if (!u_arg[0])
162                         tprintf("NULL, ");
163                 else
164                         tprintf("%#lx, ", u_arg[0]);
165                 /* len */
166                 tprintf("%lu, ", u_arg[1]);
167                 /* prot */
168                 printflags(mmap_prot, u_arg[2]);
169                 tprintf(", ");
170                 /* flags */
171                 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
172                 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
173                 /* fd */
174                 tprintf(", %ld, ", u_arg[4]);
175                 /* offset */
176                 tprintf("%#lx", u_arg[5]);
177         }
178         return RVAL_HEX;
179 }
180
181 int
182 sys_munmap(tcp)
183 struct tcb *tcp;
184 {
185         if (entering(tcp)) {
186                 tprintf("%#lx, %lu",
187                         tcp->u_arg[0], tcp->u_arg[1]);
188         }
189         return 0;
190 }
191
192 int
193 sys_mprotect(tcp)
194 struct tcb *tcp;
195 {
196         if (entering(tcp)) {
197                 tprintf("%#lx, %lu, ",
198                         tcp->u_arg[0], tcp->u_arg[1]);
199                 if (!printflags(mmap_prot, tcp->u_arg[2]))
200                         tprintf("PROT_???");
201         }
202         return 0;
203 }
204
205 #ifdef LINUX
206
207 static struct xlat mremap_flags[] = {
208         { MREMAP_MAYMOVE, "MREMAP_MAYMOVE" },
209 };
210
211 int
212 sys_mremap(tcp)
213 struct tcb *tcp;
214 {
215         if (entering(tcp)) {
216                 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
217                         tcp->u_arg[2]);
218                 printflags(mremap_flags, tcp->u_arg[3]);
219         }
220         return RVAL_HEX;
221 }
222
223 #endif /* LINUX */
224
225 #ifdef MS_ASYNC
226
227 static struct xlat mctl_sync[] = {
228         { MS_ASYNC,     "MS_ASYNC"      },
229         { MS_INVALIDATE,"MS_INVALIDATE" },
230 #ifdef MS_SYNC
231         { MS_SYNC,      "MS_SYNC"       },
232 #endif
233         { 0,            NULL            },
234 };
235
236 int
237 sys_msync(tcp)
238 struct tcb *tcp;
239 {
240         if (entering(tcp)) {
241                 /* addr */
242                 tprintf("%#lx", tcp->u_arg[0]);
243                 /* len */
244                 tprintf(", %lu, ", tcp->u_arg[1]);
245                 /* flags */
246                 if (!printflags(mctl_sync, tcp->u_arg[2]))
247                         tprintf("MS_???");
248         }
249         return 0;
250 }
251
252 #endif /* MS_ASYNC */
253
254 #ifdef MC_SYNC
255
256 static struct xlat mctl_funcs[] = {
257         { MC_LOCK,      "MC_LOCK"       },
258         { MC_LOCKAS,    "MC_LOCKAS"     },
259         { MC_SYNC,      "MC_SYNC"       },
260         { MC_UNLOCK,    "MC_UNLOCK"     },
261         { MC_UNLOCKAS,  "MC_UNLOCKAS"   },
262         { 0,            NULL            },
263 };
264
265 static struct xlat mctl_lockas[] = {
266         { MCL_CURRENT,  "MCL_CURRENT"   },
267         { MCL_FUTURE,   "MCL_FUTURE"    },
268         { 0,            NULL            },
269 };
270
271 int
272 sys_mctl(tcp)
273 struct tcb *tcp;
274 {
275         int arg, function;
276
277         if (entering(tcp)) {
278                 /* addr */
279                 tprintf("%#lx", tcp->u_arg[0]);
280                 /* len */
281                 tprintf(", %lu, ", tcp->u_arg[1]);
282                 /* function */
283                 function = tcp->u_arg[2];
284                 if (!printflags(mctl_funcs, function))
285                         tprintf("MC_???");
286                 /* arg */
287                 arg = tcp->u_arg[3];
288                 tprintf(", ");
289                 switch (function) {
290                 case MC_SYNC:
291                         if (!printflags(mctl_sync, arg))
292                                 tprintf("MS_???");
293                         break;
294                 case MC_LOCKAS:
295                         if (!printflags(mctl_lockas, arg))
296                                 tprintf("MCL_???");
297                         break;
298                 default:
299                         tprintf("%#x", arg);
300                         break;
301                 }
302         }
303         return 0;
304 }
305
306 #endif /* MC_SYNC */
307
308 int
309 sys_mincore(tcp)
310 struct tcb *tcp;
311 {
312         int i, len;
313         char *vec = NULL;
314
315         if (entering(tcp)) {
316                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
317         } else {
318                 len = tcp->u_arg[1];
319                 if (syserror(tcp) || tcp->u_arg[2] == 0 ||
320                         (vec = malloc((u_int)len)) == NULL ||
321                         umoven(tcp, tcp->u_arg[2], len, vec) < 0)
322                         tprintf("%#lx", tcp->u_arg[2]);
323                 else {
324                         tprintf("[");
325                         for (i = 0; i < len; i++) {
326                                 if (abbrev(tcp) && i >= max_strlen) {
327                                         tprintf("...");
328                                         break;
329                                 }
330                                 tprintf((vec[i] & 1) ? "1" : "0");
331                         }
332                         tprintf("]");
333                 }
334                 if (vec)
335                         free(vec);
336         }
337         return 0;
338 }
339
340 int
341 sys_getpagesize(tcp)
342 struct tcb *tcp;
343 {
344         if (exiting(tcp))
345                 return RVAL_HEX;
346         return 0;
347 }
348
349 #if defined(LINUX) && defined(__i386__)
350 int
351 sys_modify_ldt(tcp)
352 struct tcb *tcp;
353 {
354         if (entering(tcp)) {
355                 struct modify_ldt_ldt_s copy;
356                 tprintf("%ld", tcp->u_arg[0]);
357                 if (tcp->u_arg[1] == 0
358                                 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
359                                 || umove(tcp, tcp->u_arg[1], &copy) == -1)
360                         tprintf(", %lx", tcp->u_arg[1]);
361                 else {
362                         tprintf(", {entry_number:%d, ", copy.entry_number);
363                         if (!verbose(tcp))
364                                 tprintf("...}");
365                         else {
366                                 tprintf("base_addr:%#08lx, "
367                                                 "limit:%d, "
368                                                 "seg_32bit:%d, "
369                                                 "contents:%d, "
370                                                 "read_exec_only:%d, "
371                                                 "limit_in_pages:%d, "
372                                                 "seg_not_present:%d, "
373                                                 "useable:%d}",
374                                                 copy.base_addr,
375                                                 copy.limit,
376                                                 copy.seg_32bit,
377                                                 copy.contents,
378                                                 copy.read_exec_only,
379                                                 copy.limit_in_pages,
380                                                 copy.seg_not_present,
381                                                 copy.useable);
382                         }
383                 }
384                 tprintf(", %lu", tcp->u_arg[2]);
385         }
386         return 0;
387 }
388 #endif /* LINUX && __i386__ */
389