summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2017-10-30 17:56:24 +0000
committerKostya Kortchinsky <kostyak@google.com>2017-10-30 17:56:24 +0000
commit96da9fa4ca74b98acfbca63b59fb17c469cbad1c (patch)
tree7aa9db66534effdb9c041216d55115383ff7ca78
parent5da11dfd2400c8e3e6dffa34643e7967b57f8060 (diff)
downloadbcm5719-llvm-96da9fa4ca74b98acfbca63b59fb17c469cbad1c.tar.gz
bcm5719-llvm-96da9fa4ca74b98acfbca63b59fb17c469cbad1c.zip
Introduce ReservedAddressRange to sanitizer_common.
Summary: Fixed version of https://reviews.llvm.org/D38437 (fixes Win/Fuchsia failures). Creating a new revision, since the old one was getting a bit old/crowded. In Fuchsia, MmapNoAccess/MmapFixedOrDie are implemented using a global VMAR, which means that MmapNoAccess can only be called once. This works for the sanitizer allocator but *not* for the Scudo allocator. Hence, this changeset introduces a new ReservedAddressRange object to serve as the new API for these calls. In this changeset, the object still calls into the old Mmap implementations. The next changeset two changesets will convert the sanitizer and scudo allocators to use the new APIs, respectively. (ReservedAddressRange will replace the SecondaryHeader in Scudo.) Finally, a last changeset will update the Fuchsia implementation. Reviewers: alekseyshl, cryptoad, phosek Reviewed By: alekseyshl, cryptoad Subscribers: kubamracek Differential Revision: https://reviews.llvm.org/D39072 llvm-svn: 316934
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common.h14
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc24
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc30
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_win.cc30
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc67
5 files changed, 165 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index ee5eca51684..14b92d9c4a4 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -128,6 +128,20 @@ void CheckVMASize();
void RunMallocHooks(const void *ptr, uptr size);
void RunFreeHooks(const void *ptr);
+class ReservedAddressRange {
+ public:
+ uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0);
+ uptr Map(uptr fixed_addr, uptr size, bool tolerate_enomem = false);
+ void Unmap(uptr addr, uptr size);
+ void *base() const { return base_; }
+ uptr size() const { return size_; }
+
+ private:
+ void* base_;
+ uptr size_;
+ const char* name_;
+};
+
typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
/*out*/uptr *stats, uptr stats_size);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
index 21fabddb163..7d3729c689b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
@@ -236,6 +236,30 @@ void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
return DoAnonymousMmapOrDie(size, mem_type, false, false);
}
+uptr ReservedAddressRange::Init(uptr init_size, const char* name,
+ uptr fixed_addr) {
+ base_ = MmapNoAccess(init_size);
+ size_ = init_size;
+ name_ = name;
+ return reinterpret_cast<uptr>(base_);
+}
+
+// Uses fixed_addr for now.
+// Will use offset instead once we've implemented this function for real.
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size,
+ bool tolerate_enomem) {
+ return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, map_size));
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ void* addr_as_void = reinterpret_cast<void*>(addr);
+ uptr base_as_uptr = reinterpret_cast<uptr>(base_);
+ // Only unmap at the beginning or end of the range.
+ CHECK((addr_as_void == base_) || (addr + size == base_as_uptr + size_))
+ CHECK_LE(size, size_);
+ UnmapOrDie(reinterpret_cast<void*>(addr), size);
+}
+
// MmapNoAccess and MmapFixedOrDie are used only by sanitizer_allocator.
// Instead of doing exactly what they say, we make MmapNoAccess actually
// just allocate a VMAR to reserve the address space. Then MmapFixedOrDie
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
index 4214d91c535..0ba3ad46b9f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -337,6 +337,36 @@ void *MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
return (void *)p;
}
+uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
+ if (fixed_addr) {
+ base_ = MmapFixedNoAccess(fixed_addr, size, name);
+ } else {
+ base_ = MmapNoAccess(size);
+ }
+ size_ = size;
+ name_ = name;
+ return reinterpret_cast<uptr>(base_);
+}
+
+// Uses fixed_addr for now.
+// Will use offset instead once we've implemented this function for real.
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size,
+ bool tolerate_enomem) {
+ if (tolerate_enomem) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
+ }
+ return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size));
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ void* addr_as_void = reinterpret_cast<void*>(addr);
+ uptr base_as_uptr = reinterpret_cast<uptr>(base_);
+ // Only unmap at the beginning or end of the range.
+ CHECK((addr_as_void == base_) || (addr + size == base_as_uptr + size_));
+ CHECK_LE(size, size_);
+ UnmapOrDie(reinterpret_cast<void*>(addr), size);
+}
+
void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
int fd = name ? GetNamedMappingFd(name, size) : -1;
unsigned flags = MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
index 42357f6aaea..f3d4d85f70a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
@@ -235,6 +235,24 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
return p;
}
+// Uses fixed_addr for now.
+// Will use offset instead once we've implemented this function for real.
+uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size,
+ bool tolerate_enomem) {
+ if (tolerate_enomem) {
+ return reinterpret_cast<uptr>(MmapFixedOrDieOnFatalError(fixed_addr, size));
+ }
+ return reinterpret_cast<uptr>(MmapFixedOrDie(uptr fixed_addr, uptr size));
+}
+
+void ReservedAddressRange::Unmap(uptr addr, uptr size) {
+ void* addr_as_void = reinterpret_cast<void*>(addr);
+ uptr base_as_uptr = reinterpret_cast<uptr>(base_);
+ // Only unmap if it covers the entire range.
+ CHECK((addr_as_void == base_) && (size == size_));
+ UnmapOrDie(reinterpret_cast<void*>(addr), size);
+}
+
void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size) {
void *p = VirtualAlloc((LPVOID)fixed_addr, size,
MEM_COMMIT, PAGE_READWRITE);
@@ -252,6 +270,18 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
return MmapOrDie(size, mem_type);
}
+uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
+ if (fixed_addr) {
+ base_ = MmapFixedNoAccess(fixed_addr, size, name);
+ } else {
+ base_ = MmapNoAccess(size);
+ }
+ size_ = size;
+ name_ = name;
+ return reinterpret_cast<uptr>(base_);
+}
+
+
void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
(void)name; // unsupported
void *res = VirtualAlloc((LPVOID)fixed_addr, size,
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc
index 9c62b4593c6..38170ea6d63 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cc
@@ -320,4 +320,71 @@ TEST(SanitizerCommon, GetRandom) {
}
#endif
+TEST(SanitizerCommon, ReservedAddressRangeInit) {
+ uptr init_size = 0xffff;
+ ReservedAddressRange address_range;
+ uptr res = address_range.Init(init_size);
+ CHECK_NE(res, (void*)-1);
+ UnmapOrDie((void*)res, init_size);
+ // Should be able to map into the same space now.
+ ReservedAddressRange address_range2;
+ uptr res2 = address_range2.Init(init_size, nullptr, res);
+ CHECK_EQ(res, res2);
+
+ // TODO(flowerhack): Once this is switched to the "real" implementation
+ // (rather than passing through to MmapNoAccess*), enforce and test "no
+ // double initializations allowed"
+}
+
+TEST(SanitizerCommon, ReservedAddressRangeMap) {
+ constexpr uptr init_size = 0xffff;
+ ReservedAddressRange address_range;
+ uptr res = address_range.Init(init_size);
+ CHECK_NE(res, (void*) -1);
+
+ // Valid mappings should succeed.
+ CHECK_EQ(res, address_range.Map(res, init_size));
+
+ // Valid mappings should be readable.
+ unsigned char buffer[init_size];
+ memcpy(buffer, reinterpret_cast<void *>(res), init_size);
+
+ // Invalid mappings should fail.
+ EXPECT_DEATH(address_range.Map(res, 0), ".*");
+
+ // TODO(flowerhack): Once this is switched to the "real" implementation, make
+ // sure you can only mmap into offsets in the Init range.
+}
+
+TEST(SanitizerCommon, ReservedAddressRangeUnmap) {
+ uptr PageSize = GetPageSizeCached();
+ uptr init_size = PageSize * 4;
+ ReservedAddressRange address_range;
+ uptr base_addr = address_range.Init(init_size);
+ CHECK_NE(base_addr, (void*)-1);
+ CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
+
+ // Unmapping the entire range should succeed.
+ address_range.Unmap(base_addr, PageSize * 4);
+
+ // Remap that range in.
+ CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
+
+ // Windows doesn't allow partial unmappings.
+ #if !SANITIZER_WINDOWS
+
+ // Unmapping at the beginning should succeed.
+ address_range.Unmap(base_addr, PageSize);
+
+ // Unmapping at the end should succeed.
+ uptr new_start = reinterpret_cast<uptr>(address_range.base()) +
+ address_range.size() - PageSize;
+ address_range.Unmap(new_start, PageSize);
+
+ #endif
+
+ // Unmapping in the middle of the ReservedAddressRange should fail.
+ EXPECT_DEATH(address_range.Unmap(base_addr + 0xf, 0xff), ".*");
+}
+
} // namespace __sanitizer
OpenPOWER on IntegriCloud