blob: 140877eab8c5755ae085b3aa76fcb6dd78a9b642 [file] [log] [blame]
Brian Carlstromdb4d5402011-08-09 12:18:28 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_MEM_MAP_H_
18#define ART_RUNTIME_MEM_MAP_H_
Brian Carlstromdb4d5402011-08-09 12:18:28 -070019
Brian Carlstrom27ec9612011-09-19 20:20:38 -070020#include <stddef.h>
21#include <sys/types.h>
Brian Carlstromdb4d5402011-08-09 12:18:28 -070022
Andreas Gampe0dfc3152017-04-24 07:58:06 -070023#include <map>
24#include <mutex>
25#include <string>
26
27#include "android-base/thread_annotations.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070028
29namespace art {
30
Ian Rogersc3ccc102014-06-25 11:52:14 -070031#if defined(__LP64__) && (!defined(__x86_64__) || defined(__APPLE__))
32#define USE_ART_LOW_4G_ALLOCATOR 1
33#else
34#define USE_ART_LOW_4G_ALLOCATOR 0
35#endif
36
Ian Rogersc5f17732014-06-05 20:48:42 -070037#ifdef __linux__
38static constexpr bool kMadviseZeroes = true;
39#else
40static constexpr bool kMadviseZeroes = false;
41#endif
42
Brian Carlstromdb4d5402011-08-09 12:18:28 -070043// Used to keep track of mmap segments.
Andreas Gamped8f26db2014-05-19 17:01:13 -070044//
45// On 64b systems not supporting MAP_32BIT, the implementation of MemMap will do a linear scan
46// for free pages. For security, the start of this scan should be randomized. This requires a
47// dynamic initializer.
48// For this to work, it is paramount that there are no other static initializers that access MemMap.
49// Otherwise, calls might see uninitialized values.
Brian Carlstromdb4d5402011-08-09 12:18:28 -070050class MemMap {
51 public:
Elliott Hughesecd3a6f2012-06-06 18:16:37 -070052 // Request an anonymous region of length 'byte_count' and a requested base address.
Mathieu Chartier2cebb242015-04-21 16:50:40 -070053 // Use null as the requested base address if you don't care.
Vladimir Marko5c42c292015-02-25 12:02:49 +000054 // "reuse" allows re-mapping an address range from an existing mapping.
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080055 //
56 // The word "anonymous" in this context means "not backed by a file". The supplied
Nicolas Geoffraya25dce92016-01-12 16:41:10 +000057 // 'name' will be used -- on systems that support it -- to give the mapping
Elliott Hughes6c9c06d2011-11-07 16:43:47 -080058 // a name.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070059 //
Mathieu Chartier2cebb242015-04-21 16:50:40 -070060 // On success, returns returns a MemMap instance. On failure, returns null.
Nicolas Geoffraya25dce92016-01-12 16:41:10 +000061 static MemMap* MapAnonymous(const char* name,
Mathieu Chartier42bddce2015-11-09 15:16:56 -080062 uint8_t* addr,
63 size_t byte_count,
64 int prot,
65 bool low_4gb,
66 bool reuse,
Nicolas Geoffraya25dce92016-01-12 16:41:10 +000067 std::string* error_msg,
Nicolas Geoffray58a73d22016-11-29 21:49:43 +000068 bool use_ashmem = true);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070069
David Srbecky1baabf02015-06-16 17:12:34 +000070 // Create placeholder for a region allocated by direct call to mmap.
71 // This is useful when we do not have control over the code calling mmap,
72 // but when we still want to keep track of it in the list.
73 // The region is not considered to be owned and will not be unmmaped.
74 static MemMap* MapDummy(const char* name, uint8_t* addr, size_t byte_count);
75
Brian Carlstromdb4d5402011-08-09 12:18:28 -070076 // Map part of a file, taking care of non-page aligned offsets. The
77 // "start" offset is absolute, not relative.
78 //
Mathieu Chartier2cebb242015-04-21 16:50:40 -070079 // On success, returns returns a MemMap instance. On failure, returns null.
Mathieu Chartier42bddce2015-11-09 15:16:56 -080080 static MemMap* MapFile(size_t byte_count,
81 int prot,
82 int flags,
83 int fd,
84 off_t start,
85 bool low_4gb,
86 const char* filename,
87 std::string* error_msg) {
88 return MapFileAtAddress(nullptr,
89 byte_count,
90 prot,
91 flags,
92 fd,
93 start,
94 /*low_4gb*/low_4gb,
95 /*reuse*/false,
96 filename,
97 error_msg);
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070098 }
99
Mathieu Chartierebe2dfc2015-11-24 13:47:52 -0800100 // Map part of a file, taking care of non-page aligned offsets. The "start" offset is absolute,
101 // not relative. This version allows requesting a specific address for the base of the mapping.
102 // "reuse" allows us to create a view into an existing mapping where we do not take ownership of
103 // the memory. If error_msg is null then we do not print /proc/maps to the log if
104 // MapFileAtAddress fails. This helps improve performance of the fail case since reading and
105 // printing /proc/maps takes several milliseconds in the worst case.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700106 //
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700107 // On success, returns returns a MemMap instance. On failure, returns null.
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800108 static MemMap* MapFileAtAddress(uint8_t* addr,
109 size_t byte_count,
110 int prot,
111 int flags,
112 int fd,
113 off_t start,
114 bool low_4gb,
115 bool reuse,
116 const char* filename,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700117 std::string* error_msg);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700118
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700119 // Releases the memory mapping.
David Sehr1b14fb82017-02-01 10:42:11 -0800120 ~MemMap() REQUIRES(!MemMap::mem_maps_lock_);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700121
Brian Carlstrom0d6adac2014-02-05 17:39:16 -0800122 const std::string& GetName() const {
123 return name_;
124 }
125
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000126 bool Sync();
127
Logan Chiend88fa262012-06-06 15:23:32 +0800128 bool Protect(int prot);
129
Ian Rogersc5f17732014-06-05 20:48:42 -0700130 void MadviseDontNeedAndZero();
131
Ian Rogers1c849e52012-06-28 14:00:33 -0700132 int GetProtect() const {
133 return prot_;
134 }
135
Ian Rogers13735952014-10-08 12:43:28 -0700136 uint8_t* Begin() const {
Ian Rogers30fab402012-01-23 15:43:46 -0800137 return begin_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700138 }
139
Ian Rogers30fab402012-01-23 15:43:46 -0800140 size_t Size() const {
141 return size_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700142 }
143
Mathieu Chartier379d09f2015-01-08 11:28:13 -0800144 // Resize the mem-map by unmapping pages at the end. Currently only supports shrinking.
145 void SetSize(size_t new_size);
146
Ian Rogers13735952014-10-08 12:43:28 -0700147 uint8_t* End() const {
Mathieu Chartier2fde5332012-09-14 14:51:54 -0700148 return Begin() + Size();
149 }
150
Brian Carlstrom0d6adac2014-02-05 17:39:16 -0800151 void* BaseBegin() const {
152 return base_begin_;
153 }
154
155 size_t BaseSize() const {
156 return base_size_;
157 }
158
159 void* BaseEnd() const {
Ian Rogers13735952014-10-08 12:43:28 -0700160 return reinterpret_cast<uint8_t*>(BaseBegin()) + BaseSize();
Brian Carlstrom0d6adac2014-02-05 17:39:16 -0800161 }
162
Mathieu Chartier2fde5332012-09-14 14:51:54 -0700163 bool HasAddress(const void* addr) const {
164 return Begin() <= addr && addr < End();
Brian Carlstromb765be02011-08-17 23:54:10 -0700165 }
166
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700167 // Unmap the pages at end and remap them to create another memory map.
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800168 MemMap* RemapAtEnd(uint8_t* new_end,
169 const char* tail_name,
170 int tail_prot,
Nicolas Geoffraya25dce92016-01-12 16:41:10 +0000171 std::string* error_msg,
Nicolas Geoffray58a73d22016-11-29 21:49:43 +0000172 bool use_ashmem = true);
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700173
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700174 static bool CheckNoGaps(MemMap* begin_map, MemMap* end_map)
David Sehr1b14fb82017-02-01 10:42:11 -0800175 REQUIRES(!MemMap::mem_maps_lock_);
Vladimir Marko17a924a2015-05-08 15:17:32 +0100176 static void DumpMaps(std::ostream& os, bool terse = false)
David Sehr1b14fb82017-02-01 10:42:11 -0800177 REQUIRES(!MemMap::mem_maps_lock_);
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700178
David Sehr1b14fb82017-02-01 10:42:11 -0800179 // Init and Shutdown are NOT thread safe.
180 // Both may be called multiple times and MemMap objects may be created any
181 // time after the first call to Init and before the first call to Shutodwn.
182 static void Init() REQUIRES(!MemMap::mem_maps_lock_);
183 static void Shutdown() REQUIRES(!MemMap::mem_maps_lock_);
Mathieu Chartier6e88ef62014-10-14 15:01:24 -0700184
Hiroshi Yamauchi6edb9ae2016-02-08 14:18:21 -0800185 // If the map is PROT_READ, try to read each page of the map to check it is in fact readable (not
186 // faulting). This is used to diagnose a bug b/19894268 where mprotect doesn't seem to be working
187 // intermittently.
188 void TryReadable();
189
Hiroshi Yamauchi3c3c4a12017-02-21 16:49:59 -0800190 // Align the map by unmapping the unaligned parts at the lower and the higher ends.
191 void AlignBy(size_t size);
192
Andreas Gampe0dfc3152017-04-24 07:58:06 -0700193 // For annotation reasons.
194 static std::mutex* GetMemMapsLock() RETURN_CAPABILITY(mem_maps_lock_) {
195 return nullptr;
196 }
197
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700198 private:
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800199 MemMap(const std::string& name,
200 uint8_t* begin,
201 size_t size,
202 void* base_begin,
203 size_t base_size,
204 int prot,
205 bool reuse,
David Sehr1b14fb82017-02-01 10:42:11 -0800206 size_t redzone_size = 0) REQUIRES(!MemMap::mem_maps_lock_);
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700207
Vladimir Marko17a924a2015-05-08 15:17:32 +0100208 static void DumpMapsLocked(std::ostream& os, bool terse)
David Sehr1b14fb82017-02-01 10:42:11 -0800209 REQUIRES(MemMap::mem_maps_lock_);
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700210 static bool HasMemMap(MemMap* map)
David Sehr1b14fb82017-02-01 10:42:11 -0800211 REQUIRES(MemMap::mem_maps_lock_);
Hiroshi Yamauchi3eed93d2014-06-04 11:43:59 -0700212 static MemMap* GetLargestMemMapAt(void* address)
David Sehr1b14fb82017-02-01 10:42:11 -0800213 REQUIRES(MemMap::mem_maps_lock_);
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700214 static bool ContainedWithinExistingMap(uint8_t* ptr, size_t size, std::string* error_msg)
David Sehr1b14fb82017-02-01 10:42:11 -0800215 REQUIRES(!MemMap::mem_maps_lock_);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700216
Mathieu Chartier42bddce2015-11-09 15:16:56 -0800217 // Internal version of mmap that supports low 4gb emulation.
218 static void* MapInternal(void* addr,
219 size_t length,
220 int prot,
221 int flags,
222 int fd,
223 off_t offset,
224 bool low_4gb);
225
Jim_Guoa62a5882014-04-28 11:11:57 +0800226 const std::string name_;
Hiroshi Yamauchi3c3c4a12017-02-21 16:49:59 -0800227 uint8_t* begin_; // Start of data. May be changed by AlignBy.
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700228 size_t size_; // Length of data.
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700229
Hiroshi Yamauchi3c3c4a12017-02-21 16:49:59 -0800230 void* base_begin_; // Page-aligned base address. May be changed by AlignBy.
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700231 size_t base_size_; // Length of mapping. May be changed by RemapAtEnd (ie Zygote).
Ian Rogers1c849e52012-06-28 14:00:33 -0700232 int prot_; // Protection of the map.
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700233
Jim_Guoa62a5882014-04-28 11:11:57 +0800234 // When reuse_ is true, this is just a view of an existing mapping
235 // and we do not take ownership and are not responsible for
236 // unmapping.
237 const bool reuse_;
238
Evgenii Stepanov1e133742015-05-20 12:30:59 -0700239 const size_t redzone_size_;
240
Ian Rogersc3ccc102014-06-25 11:52:14 -0700241#if USE_ART_LOW_4G_ALLOCATOR
242 static uintptr_t next_mem_pos_; // Next memory location to check for low_4g extent.
Stuart Monteith8dba5aa2014-03-12 12:44:01 +0000243#endif
244
David Sehr1b14fb82017-02-01 10:42:11 -0800245 static std::mutex* mem_maps_lock_;
246
Hiroshi Yamauchifd7e7f12013-10-22 14:17:48 -0700247 friend class MemMapTest; // To allow access to base_begin_ and base_size_.
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700248};
Mathieu Chartier6e6078a2016-10-24 15:45:41 -0700249
Brian Carlstrom0d6adac2014-02-05 17:39:16 -0800250std::ostream& operator<<(std::ostream& os, const MemMap& mem_map);
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700251
Mathieu Chartier6e6078a2016-10-24 15:45:41 -0700252// Zero and release pages if possible, no requirements on alignments.
253void ZeroAndReleasePages(void* address, size_t length);
254
Brian Carlstromdb4d5402011-08-09 12:18:28 -0700255} // namespace art
256
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700257#endif // ART_RUNTIME_MEM_MAP_H_