]> granicus.if.org Git - strace/blob - mem.c
Various fixes, see ChangeLog for details
[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_FILE
128         { MAP_FILE,"MAP_FILE"},
129 #endif
130 #ifdef MAP_LOCKED
131         { MAP_LOCKED,"MAP_LOCKED"},
132 #endif
133         { 0,            NULL            },
134 };
135
136 int
137 sys_mmap(tcp)
138 struct tcb *tcp;
139 {
140 #ifdef LINUX
141 #  if defined(ALPHA) || defined(sparc)
142         long *u_arg = tcp->u_arg;
143 #  else /* !ALPHA */
144         long u_arg[6];
145 #  endif /* !ALPHA */
146 #else /* !LINUX */
147         long *u_arg = tcp->u_arg;
148 #endif /* !LINUX */
149
150         if (entering(tcp)) {
151 #if defined(LINUX) && !defined(ALPHA) && !defined(__sparc__)
152                 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
153                                 (char *) u_arg) == -1)
154                         return 0;
155 #endif /* LINUX && !ALPHA && !sparc */
156
157                 /* addr */
158                 if (!u_arg[0])
159                         tprintf("NULL, ");
160                 else
161                         tprintf("%#lx, ", u_arg[0]);
162                 /* len */
163                 tprintf("%lu, ", u_arg[1]);
164                 /* prot */
165                 printflags(mmap_prot, u_arg[2]);
166                 tprintf(", ");
167                 /* flags */
168                 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
169                 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
170                 /* fd */
171                 tprintf(", %ld, ", u_arg[4]);
172                 /* offset */
173                 tprintf("%#lx", u_arg[5]);
174         }
175         return RVAL_HEX;
176 }
177
178 int
179 sys_munmap(tcp)
180 struct tcb *tcp;
181 {
182         if (entering(tcp)) {
183                 tprintf("%#lx, %lu",
184                         tcp->u_arg[0], tcp->u_arg[1]);
185         }
186         return 0;
187 }
188
189 int
190 sys_mprotect(tcp)
191 struct tcb *tcp;
192 {
193         if (entering(tcp)) {
194                 tprintf("%#lx, %lu, ",
195                         tcp->u_arg[0], tcp->u_arg[1]);
196                 if (!printflags(mmap_prot, tcp->u_arg[2]))
197                         tprintf("PROT_???");
198         }
199         return 0;
200 }
201
202 #ifdef LINUX
203
204 static struct xlat mremap_flags[] = {
205         { MREMAP_MAYMOVE, "MREMAP_MAYMOVE" },
206 };
207
208 int
209 sys_mremap(tcp)
210 struct tcb *tcp;
211 {
212         if (entering(tcp)) {
213                 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
214                         tcp->u_arg[2]);
215                 printflags(mremap_flags, tcp->u_arg[3]);
216         }
217         return RVAL_HEX;
218 }
219
220 #endif /* LINUX */
221
222 #ifdef MS_ASYNC
223
224 static struct xlat mctl_sync[] = {
225         { MS_ASYNC,     "MS_ASYNC"      },
226         { MS_INVALIDATE,"MS_INVALIDATE" },
227 #ifdef MS_SYNC
228         { MS_SYNC,      "MS_SYNC"       },
229 #endif
230         { 0,            NULL            },
231 };
232
233 int
234 sys_msync(tcp)
235 struct tcb *tcp;
236 {
237         if (entering(tcp)) {
238                 /* addr */
239                 tprintf("%#lx", tcp->u_arg[0]);
240                 /* len */
241                 tprintf(", %lu, ", tcp->u_arg[1]);
242                 /* flags */
243                 if (!printflags(mctl_sync, tcp->u_arg[2]))
244                         tprintf("MS_???");
245         }
246         return 0;
247 }
248
249 #endif /* MS_ASYNC */
250
251 #ifdef MC_SYNC
252
253 static struct xlat mctl_funcs[] = {
254         { MC_LOCK,      "MC_LOCK"       },
255         { MC_LOCKAS,    "MC_LOCKAS"     },
256         { MC_SYNC,      "MC_SYNC"       },
257         { MC_UNLOCK,    "MC_UNLOCK"     },
258         { MC_UNLOCKAS,  "MC_UNLOCKAS"   },
259         { 0,            NULL            },
260 };
261
262 static struct xlat mctl_lockas[] = {
263         { MCL_CURRENT,  "MCL_CURRENT"   },
264         { MCL_FUTURE,   "MCL_FUTURE"    },
265         { 0,            NULL            },
266 };
267
268 int
269 sys_mctl(tcp)
270 struct tcb *tcp;
271 {
272         int arg, function;
273
274         if (entering(tcp)) {
275                 /* addr */
276                 tprintf("%#lx", tcp->u_arg[0]);
277                 /* len */
278                 tprintf(", %lu, ", tcp->u_arg[1]);
279                 /* function */
280                 function = tcp->u_arg[2];
281                 if (!printflags(mctl_funcs, function))
282                         tprintf("MC_???");
283                 /* arg */
284                 arg = tcp->u_arg[3];
285                 tprintf(", ");
286                 switch (function) {
287                 case MC_SYNC:
288                         if (!printflags(mctl_sync, arg))
289                                 tprintf("MS_???");
290                         break;
291                 case MC_LOCKAS:
292                         if (!printflags(mctl_lockas, arg))
293                                 tprintf("MCL_???");
294                         break;
295                 default:
296                         tprintf("%#x", arg);
297                         break;
298                 }
299         }
300         return 0;
301 }
302
303 #endif /* MC_SYNC */
304
305 int
306 sys_mincore(tcp)
307 struct tcb *tcp;
308 {
309         int i, len;
310         char *vec = NULL;
311
312         if (entering(tcp)) {
313                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
314         } else {
315                 len = tcp->u_arg[1];
316                 if (syserror(tcp) || tcp->u_arg[2] == 0 ||
317                         (vec = malloc((u_int)len)) == NULL ||
318                         umoven(tcp, tcp->u_arg[2], len, vec) < 0)
319                         tprintf("%#lx", tcp->u_arg[2]);
320                 else {
321                         tprintf("[");
322                         for (i = 0; i < len; i++) {
323                                 if (abbrev(tcp) && i >= max_strlen) {
324                                         tprintf("...");
325                                         break;
326                                 }
327                                 tprintf((vec[i] & 1) ? "1" : "0");
328                         }
329                         tprintf("]");
330                 }
331                 if (vec)
332                         free(vec);
333         }
334         return 0;
335 }
336
337 int
338 sys_getpagesize(tcp)
339 struct tcb *tcp;
340 {
341         if (exiting(tcp))
342                 return RVAL_HEX;
343         return 0;
344 }
345
346 #if defined(LINUX) && defined(__i386__)
347 int
348 sys_modify_ldt(tcp)
349 struct tcb *tcp;
350 {
351         if (entering(tcp)) {
352                 struct modify_ldt_ldt_s copy;
353                 tprintf("%ld", tcp->u_arg[0]);
354                 if (tcp->u_arg[1] == 0
355                                 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
356                                 || umove(tcp, tcp->u_arg[1], &copy) == -1)
357                         tprintf(", %lx", tcp->u_arg[1]);
358                 else {
359                         tprintf(", {entry_number:%d, ", copy.entry_number);
360                         if (!verbose(tcp))
361                                 tprintf("...}");
362                         else {
363                                 tprintf("base_addr:%#08lx, "
364                                                 "limit:%d, "
365                                                 "seg_32bit:%d, "
366                                                 "contents:%d, "
367                                                 "read_exec_only:%d, "
368                                                 "limit_in_pages:%d, "
369                                                 "seg_not_present:%d, "
370                                                 "useable:%d}",
371                                                 copy.base_addr,
372                                                 copy.limit,
373                                                 copy.seg_32bit,
374                                                 copy.contents,
375                                                 copy.read_exec_only,
376                                                 copy.limit_in_pages,
377                                                 copy.seg_not_present,
378                                                 copy.useable);
379                         }
380                 }
381                 tprintf(", %lu", tcp->u_arg[2]);
382         }
383         return 0;
384 }
385 #endif /* LINUX && __i386__ */
386