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