| 1 | /* GDB support for an sbrk-like function that uses mmap. |
| 2 | Copyright 1992 Free Software Foundation, Inc. |
| 3 | Contributed by Cygnus Support, using pieces from other GDB modules. |
| 4 | |
| 5 | This file is part of GDB. |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 2 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program; if not, write to the Free Software |
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
| 20 | |
| 21 | #include "defs.h" |
| 22 | |
| 23 | #ifdef HAVE_MMAP |
| 24 | |
| 25 | #include <fcntl.h> |
| 26 | #include <sys/mman.h> |
| 27 | |
| 28 | #ifdef i386 |
| 29 | #define MMAP_BASE ((caddr_t) 0x81000000) |
| 30 | #define MMAP_PGSZ 0x00002000 /* Must be multiple of real page size */ |
| 31 | #else |
| 32 | #define MMAP_BASE ((caddr_t) 0xC2000000) |
| 33 | #define MMAP_PGSZ 0x00002000 /* Must be multiple of real page size */ |
| 34 | #endif |
| 35 | |
| 36 | #define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + MMAP_PGSZ - 1) & \ |
| 37 | ~(MMAP_PGSZ - 1)) |
| 38 | |
| 39 | static caddr_t mbase = MMAP_BASE; /* Current base of mmap'd region */ |
| 40 | static caddr_t mbreak = MMAP_BASE; /* Current "break" address */ |
| 41 | static caddr_t mtop = MMAP_BASE; /* Current top of mmap'd region */ |
| 42 | |
| 43 | static int fd = -1; /* Open fd for /dev/zero */ |
| 44 | |
| 45 | |
| 46 | /* Provide a utility routine for other modules to obtain compatible |
| 47 | page alignment. */ |
| 48 | |
| 49 | PTR |
| 50 | mmap_page_align (addr) |
| 51 | PTR addr; |
| 52 | { |
| 53 | return (PAGE_ALIGN (addr)); |
| 54 | } |
| 55 | |
| 56 | /* Return the base address of the start of the mmap'd region. Note that |
| 57 | we can find the end of the region at anytime by calling mmap_sbrk(0) */ |
| 58 | |
| 59 | PTR |
| 60 | mmap_base () |
| 61 | { |
| 62 | return (mbase); |
| 63 | } |
| 64 | |
| 65 | /* Works like sbrk(), but uses mmap to add to or subtract from a |
| 66 | memory region. */ |
| 67 | |
| 68 | PTR |
| 69 | mmap_sbrk (size) |
| 70 | int size; |
| 71 | { |
| 72 | PTR result = NULL; |
| 73 | int minc; |
| 74 | caddr_t moveto; |
| 75 | |
| 76 | if (size == 0) |
| 77 | { |
| 78 | /* Just return the current "break" value. */ |
| 79 | result = mbreak; |
| 80 | } |
| 81 | else if (size < 0) |
| 82 | { |
| 83 | /* We are deallocating memory. If the amount requested would cause |
| 84 | us to try to deallocate back past the base of the mmap'd region |
| 85 | then do nothing, and return NULL. Otherwise, deallocate the |
| 86 | memory and return the old break value. */ |
| 87 | if (mbreak + size >= mbase) |
| 88 | { |
| 89 | result = (PTR) mbreak; |
| 90 | mbreak += size; |
| 91 | moveto = PAGE_ALIGN (mbreak); |
| 92 | munmap (moveto, (size_t) (mtop - moveto)); |
| 93 | mtop = moveto; |
| 94 | } |
| 95 | } |
| 96 | else |
| 97 | { |
| 98 | /* We are allocating memory. Make sure we have an open file |
| 99 | descriptor and then go on to get the memory. */ |
| 100 | if ((fd == -1) && (fd = open ("/dev/zero", O_RDONLY)) < 0) |
| 101 | { |
| 102 | result = NULL; |
| 103 | } |
| 104 | else if (mbreak + size > mtop) |
| 105 | { |
| 106 | /* The request would move us past the end of the currently |
| 107 | mapped memory, so map in enough more memory to satisfy |
| 108 | the request. */ |
| 109 | moveto = PAGE_ALIGN (mbreak + size); |
| 110 | if (mmap (mtop, moveto - mtop, PROT_READ | PROT_WRITE, |
| 111 | MAP_PRIVATE | MAP_FIXED, fd, 0) == mtop) |
| 112 | { |
| 113 | mtop = moveto; |
| 114 | result = (PTR) mbreak; |
| 115 | mbreak += size; |
| 116 | } |
| 117 | } |
| 118 | else |
| 119 | { |
| 120 | result = (PTR) mbreak; |
| 121 | mbreak += size; |
| 122 | } |
| 123 | } |
| 124 | return (result); |
| 125 | } |
| 126 | |
| 127 | PTR |
| 128 | mmap_remap (base, mapsize, fd, foffset) |
| 129 | PTR base; |
| 130 | long mapsize; |
| 131 | int fd; |
| 132 | long foffset; |
| 133 | { |
| 134 | /* FIXME: Quick hack, needs error checking and other attention. */ |
| 135 | munmap (mbase, (size_t) (mtop - mbase)); |
| 136 | mbase = base; |
| 137 | mtop = mbase + mapsize; |
| 138 | base = mmap (base, mapsize, PROT_READ | PROT_WRITE, |
| 139 | MAP_PRIVATE | MAP_FIXED, dup (fd), foffset); |
| 140 | return (base); |
| 141 | } |
| 142 | |
| 143 | |
| 144 | #endif /* HAVE_MMAP */ |