]> granicus.if.org Git - strace/blob - mem.c
replace wimpy get64 by powerful LONG_LONG :-)
[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  * 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 #ifdef LINUX
36 #include <linux/mman.h>
37 #endif
38 #include <sys/mman.h>
39
40 #if defined(LINUX) && defined(__i386__)
41 #include <asm/ldt.h>
42 #endif
43
44 #ifdef HAVE_LONG_LONG_OFF_T
45 /*
46  * Ugly hacks for systems that have a long long off_t
47  */
48 #define sys_mmap64      sys_mmap
49 #endif
50
51 int
52 sys_brk(tcp)
53 struct tcb *tcp;
54 {
55         if (entering(tcp)) {
56                 tprintf("%#lx", tcp->u_arg[0]);
57         }
58 #ifdef LINUX
59         return RVAL_HEX;
60 #else
61         return 0;
62 #endif
63 }
64
65 int
66 sys_sbrk(tcp)
67 struct tcb *tcp;
68 {
69         if (entering(tcp)) {
70                 tprintf("%lu", tcp->u_arg[0]);
71         }
72         return RVAL_HEX;
73 }
74
75 static struct xlat mmap_prot[] = {
76         { PROT_NONE,    "PROT_NONE",    },
77         { PROT_READ,    "PROT_READ"     },
78         { PROT_WRITE,   "PROT_WRITE"    },
79         { PROT_EXEC,    "PROT_EXEC"     },
80         { 0,            NULL            },
81 };
82
83 static struct xlat mmap_flags[] = {
84         { MAP_SHARED,   "MAP_SHARED"    },
85         { MAP_PRIVATE,  "MAP_PRIVATE"   },
86         { MAP_FIXED,    "MAP_FIXED"     },
87 #ifdef MAP_ANONYMOUS
88         { MAP_ANONYMOUS,"MAP_ANONYMOUS" },
89 #endif
90 #ifdef MAP_RENAME
91         { MAP_RENAME,   "MAP_RENAME"    },
92 #endif
93 #ifdef MAP_NORESERVE
94         { MAP_NORESERVE,"MAP_NORESERVE" },
95 #endif
96         /*
97          * XXX - this was introduced in SunOS 4.x to distinguish between
98          * the old pre-4.x "mmap()", which:
99          *
100          *      only let you map devices with an "mmap" routine (e.g.,
101          *      frame buffers) in;
102          *
103          *      required you to specify the mapping address;
104          *
105          *      returned 0 on success and -1 on failure;
106          *
107          * memory and which, and the 4.x "mmap()" which:
108          *
109          *      can map plain files;
110          *
111          *      can be asked to pick where to map the file;
112          *
113          *      returns the address where it mapped the file on success
114          *      and -1 on failure.
115          *
116          * It's not actually used in source code that calls "mmap()"; the
117          * "mmap()" routine adds it for you.
118          *
119          * It'd be nice to come up with some way of eliminating it from
120          * the flags, e.g. reporting calls *without* it as "old_mmap()"
121          * and calls with it as "mmap()".
122          */
123 #ifdef _MAP_NEW
124         { _MAP_NEW,     "_MAP_NEW"      },
125 #endif
126 #ifdef MAP_GROWSDOWN
127         { MAP_GROWSDOWN,"MAP_GROWSDOWN" },
128 #endif
129 #ifdef MAP_DENYWRITE
130         { MAP_DENYWRITE,"MAP_DENYWRITE" },
131 #endif
132 #ifdef MAP_EXECUTABLE
133         { MAP_EXECUTABLE,"MAP_EXECUTABLE"},
134 #endif
135 #ifdef MAP_INHERIT
136         { MAP_INHERIT,"MAP_INHERIT"     },
137 #endif
138 #ifdef MAP_FILE
139         { MAP_FILE,"MAP_FILE"},
140 #endif
141 #ifdef MAP_LOCKED
142         { MAP_LOCKED,"MAP_LOCKED"},
143 #endif
144         /* FreeBSD ones */
145 #ifdef MAP_ANON
146         { MAP_ANON,             "MAP_ANON"      },
147 #endif
148 #ifdef MAP_HASSEMAPHORE
149         { MAP_HASSEMAPHORE,     "MAP_HASSEMAPHORE"      },
150 #endif
151 #ifdef MAP_STACK
152         { MAP_STACK,            "MAP_STACK"     },
153 #endif
154 #ifdef MAP_NOSYNC
155         { MAP_NOSYNC,           "MAP_NOSYNC"    },
156 #endif
157 #ifdef MAP_NOCORE
158         { MAP_NOCORE,           "MAP_NOCORE"    },
159 #endif
160         { 0,            NULL            },
161 };
162
163 #if !HAVE_LONG_LONG_OFF_T
164 static
165 int
166 print_mmap(tcp,u_arg)
167 struct tcb *tcp;
168 long *u_arg;
169 {
170         if (entering(tcp)) {
171                 /* addr */
172                 if (!u_arg[0])
173                         tprintf("NULL, ");
174                 else
175                         tprintf("%#lx, ", u_arg[0]);
176                 /* len */
177                 tprintf("%lu, ", u_arg[1]);
178                 /* prot */
179                 printflags(mmap_prot, u_arg[2]);
180                 tprintf(", ");
181                 /* flags */
182 #ifdef MAP_TYPE
183                 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
184                 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
185 #else
186                 printflags(mmap_flags, u_arg[3]);
187 #endif
188                 /* fd */
189                 tprintf(", %ld, ", u_arg[4]);
190                 /* offset */
191                 tprintf("%#lx", u_arg[5]);
192         }
193         return RVAL_HEX;
194 }
195
196 #ifdef LINUX
197 int sys_old_mmap(tcp)
198 struct tcb *tcp;
199 {
200     long u_arg[6];
201
202 #if     defined(IA64)
203     int i, v;
204     /*
205      *  IA64 processes never call this routine, they only use the
206      *  new `sys_mmap' interface.  This code converts the integer
207      *  arguments that the IA32 process pushed onto the stack into
208      *  longs.
209      *
210      *  Note that addresses with bit 31 set will be sign extended.
211      *  Fortunately, those addresses are not currently being generated
212      *  for IA32 processes so it's not a problem.
213      */
214     for (i = 0; i < 6; i++)
215         if (umove(tcp, tcp->u_arg[0] + (i * sizeof(int)), &v) == -1)
216                 return 0;
217         else
218                 u_arg[i] = v;
219 #else   // defined(IA64)
220     if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1)
221             return 0;
222 #endif  // defined(IA64)
223     return print_mmap(tcp, u_arg);
224    
225 }
226 #endif
227
228 int
229 sys_mmap(tcp)
230 struct tcb *tcp;
231 {
232     return print_mmap(tcp, tcp->u_arg);
233 }
234 #endif /* !HAVE_LONG_LONG_OFF_T */
235
236 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
237 int
238 sys_mmap64(tcp)
239 struct tcb *tcp;
240 {
241 #ifdef linux
242 #ifdef ALPHA
243         long *u_arg = tcp->u_arg;
244 #else /* !ALPHA */
245         long u_arg[7];
246 #endif /* !ALPHA */
247 #else /* !linux */
248         long *u_arg = tcp->u_arg;
249 #endif /* !linux */
250
251         if (entering(tcp)) {
252 #ifdef linux
253 #ifndef ALPHA
254                 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
255                                 (char *) u_arg) == -1)
256                         return 0;
257 #endif /* ALPHA */
258 #endif /* linux */
259                 ALIGN64 (tcp, 5);       /* FreeBSD wierdies */
260
261                 /* addr */
262                 tprintf("%#lx, ", u_arg[0]);
263                 /* len */
264                 tprintf("%lu, ", u_arg[1]);
265                 /* prot */
266                 printflags(mmap_prot, u_arg[2]);
267                 tprintf(", ");
268                 /* flags */
269 #ifdef MAP_TYPE
270                 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
271                 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
272 #else
273                 printflags(mmap_flags, u_arg[3]);
274 #endif
275                 /* fd */
276                 tprintf(", %ld, ", u_arg[4]);
277                 /* offset */
278                 tprintf("%#llx", LONG_LONG(u_arg[5], u_arg[6]));
279         }
280         return RVAL_HEX;
281 }
282 #endif
283
284  
285 int
286 sys_munmap(tcp)
287 struct tcb *tcp;
288 {
289         if (entering(tcp)) {
290                 tprintf("%#lx, %lu",
291                         tcp->u_arg[0], tcp->u_arg[1]);
292         }
293         return 0;
294 }
295
296 int
297 sys_mprotect(tcp)
298 struct tcb *tcp;
299 {
300         if (entering(tcp)) {
301                 tprintf("%#lx, %lu, ",
302                         tcp->u_arg[0], tcp->u_arg[1]);
303                 if (!printflags(mmap_prot, tcp->u_arg[2]))
304                         tprintf("PROT_???");
305         }
306         return 0;
307 }
308
309 #ifdef LINUX
310
311 static struct xlat mremap_flags[] = {
312         { MREMAP_MAYMOVE,       "MREMAP_MAYMOVE"        },
313         { 0,                    NULL                    }
314 };
315
316 int
317 sys_mremap(tcp)
318 struct tcb *tcp;
319 {
320         if (entering(tcp)) {
321                 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
322                         tcp->u_arg[2]);
323                 printflags(mremap_flags, tcp->u_arg[3]);
324         }
325         return RVAL_HEX;
326 }
327
328 static struct xlat madvise_flags[] = {
329 #ifdef MADV_NORMAL
330         { MADV_NORMAL,          "MADV_NORMAL" },
331 #endif
332 #ifdef MADZV_RANDOM
333         { MADV_RANDOM,          "MADV_RANDOM" },
334 #endif
335 #ifdef MADV_SEQUENTIAL
336         { MADV_SEQUENTIAL,      "MADV_SEQUENTIAL" },
337 #endif
338 #ifdef MADV_WILLNEED
339         { MADV_WILLNEED,        "MADV_WILLNEED" },
340 #endif
341 #ifdef MADV_DONTNED
342         { MADV_DONTNEED,        "MADV_DONTNEED" },
343 #endif
344         { 0,                    NULL },
345 };
346
347
348 int
349 sys_madvise(tcp)
350 struct tcb *tcp;
351 {
352         if (entering(tcp)) {
353                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
354                 printflags(madvise_flags, tcp->u_arg[2]);
355         }
356         return 0;
357 }
358
359
360 static struct xlat mlockall_flags[] = {
361 #ifdef MCL_CURRENT
362         { MCL_CURRENT,  "MCL_CURRENT" },
363 #endif
364 #ifdef MCL_FUTURE
365         { MCL_FUTURE,   "MCL_FUTURE" },
366 #endif
367         { 0,            NULL}
368 };
369
370 int
371 sys_mlockall(tcp)
372 struct tcb *tcp;
373 {
374         if (entering(tcp)) {
375                 printflags(mlockall_flags, tcp->u_arg[0]);
376         }
377         return 0;
378 }
379
380
381 #endif /* LINUX */
382
383 #ifdef MS_ASYNC
384
385 static struct xlat mctl_sync[] = {
386         { MS_ASYNC,     "MS_ASYNC"      },
387         { MS_INVALIDATE,"MS_INVALIDATE" },
388 #ifdef MS_SYNC
389         { MS_SYNC,      "MS_SYNC"       },
390 #endif
391         { 0,            NULL            },
392 };
393
394 int
395 sys_msync(tcp)
396 struct tcb *tcp;
397 {
398         if (entering(tcp)) {
399                 /* addr */
400                 tprintf("%#lx", tcp->u_arg[0]);
401                 /* len */
402                 tprintf(", %lu, ", tcp->u_arg[1]);
403                 /* flags */
404                 if (!printflags(mctl_sync, tcp->u_arg[2]))
405                         tprintf("MS_???");
406         }
407         return 0;
408 }
409
410 #endif /* MS_ASYNC */
411
412 #ifdef MC_SYNC
413
414 static struct xlat mctl_funcs[] = {
415         { MC_LOCK,      "MC_LOCK"       },
416         { MC_LOCKAS,    "MC_LOCKAS"     },
417         { MC_SYNC,      "MC_SYNC"       },
418         { MC_UNLOCK,    "MC_UNLOCK"     },
419         { MC_UNLOCKAS,  "MC_UNLOCKAS"   },
420         { 0,            NULL            },
421 };
422
423 static struct xlat mctl_lockas[] = {
424         { MCL_CURRENT,  "MCL_CURRENT"   },
425         { MCL_FUTURE,   "MCL_FUTURE"    },
426         { 0,            NULL            },
427 };
428
429 int
430 sys_mctl(tcp)
431 struct tcb *tcp;
432 {
433         int arg, function;
434
435         if (entering(tcp)) {
436                 /* addr */
437                 tprintf("%#lx", tcp->u_arg[0]);
438                 /* len */
439                 tprintf(", %lu, ", tcp->u_arg[1]);
440                 /* function */
441                 function = tcp->u_arg[2];
442                 if (!printflags(mctl_funcs, function))
443                         tprintf("MC_???");
444                 /* arg */
445                 arg = tcp->u_arg[3];
446                 tprintf(", ");
447                 switch (function) {
448                 case MC_SYNC:
449                         if (!printflags(mctl_sync, arg))
450                                 tprintf("MS_???");
451                         break;
452                 case MC_LOCKAS:
453                         if (!printflags(mctl_lockas, arg))
454                                 tprintf("MCL_???");
455                         break;
456                 default:
457                         tprintf("%#x", arg);
458                         break;
459                 }
460         }
461         return 0;
462 }
463
464 #endif /* MC_SYNC */
465
466 int
467 sys_mincore(tcp)
468 struct tcb *tcp;
469 {
470         int i, len;
471         char *vec = NULL;
472
473         if (entering(tcp)) {
474                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
475         } else {
476                 len = tcp->u_arg[1];
477                 if (syserror(tcp) || tcp->u_arg[2] == 0 ||
478                         (vec = malloc((u_int)len)) == NULL ||
479                         umoven(tcp, tcp->u_arg[2], len, vec) < 0)
480                         tprintf("%#lx", tcp->u_arg[2]);
481                 else {
482                         tprintf("[");
483                         for (i = 0; i < len; i++) {
484                                 if (abbrev(tcp) && i >= max_strlen) {
485                                         tprintf("...");
486                                         break;
487                                 }
488                                 tprintf((vec[i] & 1) ? "1" : "0");
489                         }
490                         tprintf("]");
491                 }
492                 if (vec)
493                         free(vec);
494         }
495         return 0;
496 }
497
498 int
499 sys_getpagesize(tcp)
500 struct tcb *tcp;
501 {
502         if (exiting(tcp))
503                 return RVAL_HEX;
504         return 0;
505 }
506
507 #if defined(LINUX) && defined(__i386__)
508 int
509 sys_modify_ldt(tcp)
510 struct tcb *tcp;
511 {
512         if (entering(tcp)) {
513                 struct modify_ldt_ldt_s copy;
514                 tprintf("%ld", tcp->u_arg[0]);
515                 if (tcp->u_arg[1] == 0
516                                 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
517                                 || umove(tcp, tcp->u_arg[1], &copy) == -1)
518                         tprintf(", %lx", tcp->u_arg[1]);
519                 else {
520                         tprintf(", {entry_number:%d, ", copy.entry_number);
521                         if (!verbose(tcp))
522                                 tprintf("...}");
523                         else {
524                                 tprintf("base_addr:%#08lx, "
525                                                 "limit:%d, "
526                                                 "seg_32bit:%d, "
527                                                 "contents:%d, "
528                                                 "read_exec_only:%d, "
529                                                 "limit_in_pages:%d, "
530                                                 "seg_not_present:%d, "
531                                                 "useable:%d}",
532                                                 copy.base_addr,
533                                                 copy.limit,
534                                                 copy.seg_32bit,
535                                                 copy.contents,
536                                                 copy.read_exec_only,
537                                                 copy.limit_in_pages,
538                                                 copy.seg_not_present,
539                                                 copy.useable);
540                         }
541                 }
542                 tprintf(", %lu", tcp->u_arg[2]);
543         }
544         return 0;
545 }
546 #endif /* LINUX && __i386__ */
547