Verify there's no mem map gap for immune region not to break.
This adds code that verifies that there's no memory map gap between
the image space and the main space so that the immune region
functionality won't silently break. For example, if there's a gap and
a large object is allocated in that gap, the large object is
incorrectly part of the immune region and the marking breaks.
Bug: 14059466
Change-Id: Ie6ed82988d74b6d0562ebbbaac96ee43c15b14a6
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index 1411856..dc5909b 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -17,7 +17,10 @@
#ifndef ART_RUNTIME_MEM_MAP_H_
#define ART_RUNTIME_MEM_MAP_H_
+#include "base/mutex.h"
+
#include <string>
+#include <map>
#include <stddef.h>
#include <sys/mman.h> // For the PROT_* and MAP_* constants.
@@ -66,7 +69,7 @@
std::string* error_msg);
// Releases the memory mapping
- ~MemMap();
+ ~MemMap() LOCKS_EXCLUDED(Locks::mem_maps_lock_);
const std::string& GetName() const {
return name_;
@@ -110,9 +113,23 @@
MemMap* RemapAtEnd(byte* new_end, const char* tail_name, int tail_prot,
std::string* error_msg);
+ static bool CheckNoGaps(MemMap* begin_map, MemMap* end_map)
+ LOCKS_EXCLUDED(Locks::mem_maps_lock_);
+ static void DumpMaps(std::ostream& os)
+ LOCKS_EXCLUDED(Locks::mem_maps_lock_);
+
private:
MemMap(const std::string& name, byte* begin, size_t size, void* base_begin, size_t base_size,
- int prot);
+ int prot) LOCKS_EXCLUDED(Locks::mem_maps_lock_);
+
+ static void DumpMaps(std::ostream& os, const std::multimap<void*, MemMap*>& mem_maps)
+ LOCKS_EXCLUDED(Locks::mem_maps_lock_);
+ static void DumpMapsLocked(std::ostream& os, const std::multimap<void*, MemMap*>& mem_maps)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);
+ static bool HasMemMap(MemMap* map)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);
+ static MemMap* GetLargestMemMapAt(void* address)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mem_maps_lock_);
std::string name_;
byte* const begin_; // Start of data.
@@ -126,6 +143,9 @@
static uintptr_t next_mem_pos_; // next memory location to check for low_4g extent
#endif
+ // All the non-empty MemMaps. Use a multimap as we do a reserve-and-divide (eg ElfMap::Load()).
+ static std::multimap<void*, MemMap*> maps_ GUARDED_BY(Locks::mem_maps_lock_);
+
friend class MemMapTest; // To allow access to base_begin_ and base_size_.
};
std::ostream& operator<<(std::ostream& os, const MemMap& mem_map);