]> granicus.if.org Git - strace/blob - mem.c
2003-02-26 Stuart Menefy <stuart.menefy@st.com>
[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 #elif defined(SH)
226     /* SH has always passed the args in registers */
227     int i;
228     for (i=0; i<6; i++)
229         u_arg[i] = tcp->u_arg[i];
230 #else
231     if (umoven(tcp, tcp->u_arg[0], sizeof u_arg, (char *) u_arg) == -1)
232             return 0;
233 #endif  // defined(IA64)
234     return print_mmap(tcp, u_arg);
235
236 }
237 #endif
238
239 int
240 sys_mmap(tcp)
241 struct tcb *tcp;
242 {
243     return print_mmap(tcp, tcp->u_arg);
244 }
245 #endif /* !HAVE_LONG_LONG_OFF_T */
246
247 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
248 int
249 sys_mmap64(tcp)
250 struct tcb *tcp;
251 {
252 #ifdef linux
253 #ifdef ALPHA
254         long *u_arg = tcp->u_arg;
255 #else /* !ALPHA */
256         long u_arg[7];
257 #endif /* !ALPHA */
258 #else /* !linux */
259         long *u_arg = tcp->u_arg;
260 #endif /* !linux */
261
262         if (entering(tcp)) {
263 #ifdef linux
264 #ifndef ALPHA
265                 if (umoven(tcp, tcp->u_arg[0], sizeof u_arg,
266                                 (char *) u_arg) == -1)
267                         return 0;
268 #endif /* ALPHA */
269 #endif /* linux */
270                 ALIGN64 (tcp, 5);       /* FreeBSD wierdies */
271
272                 /* addr */
273                 tprintf("%#lx, ", u_arg[0]);
274                 /* len */
275                 tprintf("%lu, ", u_arg[1]);
276                 /* prot */
277                 printflags(mmap_prot, u_arg[2]);
278                 tprintf(", ");
279                 /* flags */
280 #ifdef MAP_TYPE
281                 printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
282                 addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
283 #else
284                 printflags(mmap_flags, u_arg[3]);
285 #endif
286                 /* fd */
287                 tprintf(", %ld, ", u_arg[4]);
288                 /* offset */
289                 tprintf("%#llx", LONG_LONG(u_arg[5], u_arg[6]));
290         }
291         return RVAL_HEX;
292 }
293 #endif
294
295
296 int
297 sys_munmap(tcp)
298 struct tcb *tcp;
299 {
300         if (entering(tcp)) {
301                 tprintf("%#lx, %lu",
302                         tcp->u_arg[0], tcp->u_arg[1]);
303         }
304         return 0;
305 }
306
307 int
308 sys_mprotect(tcp)
309 struct tcb *tcp;
310 {
311         if (entering(tcp)) {
312                 tprintf("%#lx, %lu, ",
313                         tcp->u_arg[0], tcp->u_arg[1]);
314                 if (!printflags(mmap_prot, tcp->u_arg[2]))
315                         tprintf("PROT_???");
316         }
317         return 0;
318 }
319
320 #ifdef LINUX
321
322 static struct xlat mremap_flags[] = {
323         { MREMAP_MAYMOVE,       "MREMAP_MAYMOVE"        },
324         { 0,                    NULL                    }
325 };
326
327 int
328 sys_mremap(tcp)
329 struct tcb *tcp;
330 {
331         if (entering(tcp)) {
332                 tprintf("%#lx, %lu, %lu, ", tcp->u_arg[0], tcp->u_arg[1],
333                         tcp->u_arg[2]);
334                 printflags(mremap_flags, tcp->u_arg[3]);
335         }
336         return RVAL_HEX;
337 }
338
339 static struct xlat madvise_flags[] = {
340 #ifdef MADV_NORMAL
341         { MADV_NORMAL,          "MADV_NORMAL" },
342 #endif
343 #ifdef MADZV_RANDOM
344         { MADV_RANDOM,          "MADV_RANDOM" },
345 #endif
346 #ifdef MADV_SEQUENTIAL
347         { MADV_SEQUENTIAL,      "MADV_SEQUENTIAL" },
348 #endif
349 #ifdef MADV_WILLNEED
350         { MADV_WILLNEED,        "MADV_WILLNEED" },
351 #endif
352 #ifdef MADV_DONTNED
353         { MADV_DONTNEED,        "MADV_DONTNEED" },
354 #endif
355         { 0,                    NULL },
356 };
357
358
359 int
360 sys_madvise(tcp)
361 struct tcb *tcp;
362 {
363         if (entering(tcp)) {
364                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
365                 printflags(madvise_flags, tcp->u_arg[2]);
366         }
367         return 0;
368 }
369
370
371 static struct xlat mlockall_flags[] = {
372 #ifdef MCL_CURRENT
373         { MCL_CURRENT,  "MCL_CURRENT" },
374 #endif
375 #ifdef MCL_FUTURE
376         { MCL_FUTURE,   "MCL_FUTURE" },
377 #endif
378         { 0,            NULL}
379 };
380
381 int
382 sys_mlockall(tcp)
383 struct tcb *tcp;
384 {
385         if (entering(tcp)) {
386                 printflags(mlockall_flags, tcp->u_arg[0]);
387         }
388         return 0;
389 }
390
391
392 #endif /* LINUX */
393
394 #ifdef MS_ASYNC
395
396 static struct xlat mctl_sync[] = {
397 #ifdef MS_SYNC
398         { MS_SYNC,      "MS_SYNC"       },
399 #endif
400         { MS_ASYNC,     "MS_ASYNC"      },
401         { MS_INVALIDATE,"MS_INVALIDATE" },
402         { 0,            NULL            },
403 };
404
405 int
406 sys_msync(tcp)
407 struct tcb *tcp;
408 {
409         if (entering(tcp)) {
410                 /* addr */
411                 tprintf("%#lx", tcp->u_arg[0]);
412                 /* len */
413                 tprintf(", %lu, ", tcp->u_arg[1]);
414                 /* flags */
415                 if (!printflags(mctl_sync, tcp->u_arg[2]))
416                         tprintf("MS_???");
417         }
418         return 0;
419 }
420
421 #endif /* MS_ASYNC */
422
423 #ifdef MC_SYNC
424
425 static struct xlat mctl_funcs[] = {
426         { MC_LOCK,      "MC_LOCK"       },
427         { MC_LOCKAS,    "MC_LOCKAS"     },
428         { MC_SYNC,      "MC_SYNC"       },
429         { MC_UNLOCK,    "MC_UNLOCK"     },
430         { MC_UNLOCKAS,  "MC_UNLOCKAS"   },
431         { 0,            NULL            },
432 };
433
434 static struct xlat mctl_lockas[] = {
435         { MCL_CURRENT,  "MCL_CURRENT"   },
436         { MCL_FUTURE,   "MCL_FUTURE"    },
437         { 0,            NULL            },
438 };
439
440 int
441 sys_mctl(tcp)
442 struct tcb *tcp;
443 {
444         int arg, function;
445
446         if (entering(tcp)) {
447                 /* addr */
448                 tprintf("%#lx", tcp->u_arg[0]);
449                 /* len */
450                 tprintf(", %lu, ", tcp->u_arg[1]);
451                 /* function */
452                 function = tcp->u_arg[2];
453                 if (!printflags(mctl_funcs, function))
454                         tprintf("MC_???");
455                 /* arg */
456                 arg = tcp->u_arg[3];
457                 tprintf(", ");
458                 switch (function) {
459                 case MC_SYNC:
460                         if (!printflags(mctl_sync, arg))
461                                 tprintf("MS_???");
462                         break;
463                 case MC_LOCKAS:
464                         if (!printflags(mctl_lockas, arg))
465                                 tprintf("MCL_???");
466                         break;
467                 default:
468                         tprintf("%#x", arg);
469                         break;
470                 }
471         }
472         return 0;
473 }
474
475 #endif /* MC_SYNC */
476
477 int
478 sys_mincore(tcp)
479 struct tcb *tcp;
480 {
481         int i, len;
482         char *vec = NULL;
483
484         if (entering(tcp)) {
485                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
486         } else {
487                 len = tcp->u_arg[1];
488                 if (syserror(tcp) || tcp->u_arg[2] == 0 ||
489                         (vec = malloc((u_int)len)) == NULL ||
490                         umoven(tcp, tcp->u_arg[2], len, vec) < 0)
491                         tprintf("%#lx", tcp->u_arg[2]);
492                 else {
493                         tprintf("[");
494                         for (i = 0; i < len; i++) {
495                                 if (abbrev(tcp) && i >= max_strlen) {
496                                         tprintf("...");
497                                         break;
498                                 }
499                                 tprintf((vec[i] & 1) ? "1" : "0");
500                         }
501                         tprintf("]");
502                 }
503                 if (vec)
504                         free(vec);
505         }
506         return 0;
507 }
508
509 int
510 sys_getpagesize(tcp)
511 struct tcb *tcp;
512 {
513         if (exiting(tcp))
514                 return RVAL_HEX;
515         return 0;
516 }
517
518 #if defined(LINUX) && defined(__i386__)
519 void
520 print_ldt_entry (ldt_entry)
521 struct modify_ldt_ldt_s *ldt_entry;
522 {
523         tprintf("base_addr:%#08lx, "
524                 "limit:%d, "
525                 "seg_32bit:%d, "
526                 "contents:%d, "
527                 "read_exec_only:%d, "
528                 "limit_in_pages:%d, "
529                 "seg_not_present:%d, "
530                 "useable:%d}",
531                 ldt_entry->base_addr,
532                 ldt_entry->limit,
533                 ldt_entry->seg_32bit,
534                 ldt_entry->contents,
535                 ldt_entry->read_exec_only,
536                 ldt_entry->limit_in_pages,
537                 ldt_entry->seg_not_present,
538                 ldt_entry->useable);
539 }
540
541 int
542 sys_modify_ldt(tcp)
543 struct tcb *tcp;
544 {
545         if (entering(tcp)) {
546                 struct modify_ldt_ldt_s copy;
547                 tprintf("%ld", tcp->u_arg[0]);
548                 if (tcp->u_arg[1] == 0
549                                 || tcp->u_arg[2] != sizeof (struct modify_ldt_ldt_s)
550                                 || umove(tcp, tcp->u_arg[1], &copy) == -1)
551                         tprintf(", %lx", tcp->u_arg[1]);
552                 else {
553                         tprintf(", {entry_number:%d, ", copy.entry_number);
554                         if (!verbose(tcp))
555                                 tprintf("...}");
556                         else {
557                                 print_ldt_entry(&copy);
558                         }
559                 }
560                 tprintf(", %lu", tcp->u_arg[2]);
561         }
562         return 0;
563 }
564
565 int
566 sys_set_thread_area(tcp)
567 struct tcb *tcp;
568 {
569         struct modify_ldt_ldt_s copy;
570         if (entering(tcp)) {
571                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
572                         if (copy.entry_number == -1)
573                                 tprintf("{entry_number:%d -> ",
574                                         copy.entry_number);
575                         else
576                                 tprintf("{entry_number:");
577                 }
578         } else {
579                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
580                         tprintf("%d, ", copy.entry_number);
581                         if (!verbose(tcp))
582                                 tprintf("...}");
583                         else {
584                                 print_ldt_entry(&copy);
585                         }
586                 } else {
587                         tprintf("%lx", tcp->u_arg[0]);
588                 }
589         }
590         return 0;
591
592 }
593
594 int
595 sys_get_thread_area(tcp)
596 struct tcb *tcp;
597 {
598         struct modify_ldt_ldt_s copy;
599         if (exiting(tcp)) {
600                 if (umove(tcp, tcp->u_arg[0], &copy) != -1) {
601                         tprintf("{entry_number:%d, ", copy.entry_number);
602                         if (!verbose(tcp))
603                                 tprintf("...}");
604                         else {
605                                 print_ldt_entry(&copy);
606                         }
607                 } else {
608                         tprintf("%lx", tcp->u_arg[0]);
609                 }
610         }
611         return 0;
612
613 }
614 #endif /* LINUX && __i386__ */
615
616 #if defined(LINUX)
617 int
618 sys_remap_file_pages(tcp)
619 struct tcb *tcp;
620 {
621         if (entering(tcp)) {
622                 tprintf("%#lx, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
623                 printflags(mmap_prot, tcp->u_arg[2]);
624                 tprintf(", %lu, ", tcp->u_arg[3]);
625 #ifdef MAP_TYPE
626                 printxval(mmap_flags, tcp->u_arg[4] & MAP_TYPE, "MAP_???");
627                 addflags(mmap_flags, tcp->u_arg[4] & ~MAP_TYPE);
628 #else
629                 printflags(mmap_flags, tcp->u_arg[4]);
630 #endif
631         }
632         return 0;
633 }
634 #endif