Fix valgrind errors with MemMap::Sync().

This fixes valgrind-test-art-host-gtest-oat_test and one error in
valgrind-test-art-host-gtest-image_test32.

Valgrind doesn't like it if an address range that contains noaccess or
uninitialized memory is passed to msync(). Temporarily lift the noaccess
protection of the lower-end redzone because msync accepts a page-aligned
base address only and exclude the higher-end noaccess redzone from the
range.

Bug: 27552451
Bug: 27384445
Change-Id: I8ccbd04c62eb30f6c6d5c732f1eb254fa09a417a
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 11156c6..421641c 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -590,7 +590,19 @@
 }
 
 bool MemMap::Sync() {
-  return msync(BaseBegin(), BaseSize(), MS_SYNC) == 0;
+  bool result;
+  if (redzone_size_ != 0) {
+    // To avoid valgrind errors, temporarily lift the lower-end noaccess protection before passing
+    // it to msync() as it only accepts page-aligned base address, and exclude the higher-end
+    // noaccess protection from the msync range. b/27552451.
+    uint8_t* base_begin = reinterpret_cast<uint8_t*>(base_begin_);
+    MEMORY_TOOL_MAKE_DEFINED(base_begin, begin_ - base_begin);
+    result = msync(BaseBegin(), End() - base_begin, MS_SYNC) == 0;
+    MEMORY_TOOL_MAKE_NOACCESS(base_begin, begin_ - base_begin);
+  } else {
+    result = msync(BaseBegin(), BaseSize(), MS_SYNC) == 0;
+  }
+  return result;
 }
 
 bool MemMap::Protect(int prot) {