Allow MemMap to support empty map requests

Discovered trying to use ZipEntry::ExtractToMemMap on an empty preloaded-classes.

Bug: 8659045
Change-Id: Icfbbe6b313e2d1ee708b44a8d8d354d6203fd669
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index ad33365..6a73fc0 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -39,6 +39,7 @@
 	runtime/indirect_reference_table_test.cc \
 	runtime/intern_table_test.cc \
 	runtime/jni_internal_test.cc \
+	runtime/mem_map_test.cc \
 	runtime/mirror/dex_cache_test.cc \
 	runtime/mirror/object_test.cc \
 	runtime/oat/utils/arm/managed_register_arm_test.cc \
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 619b73c..9a34610 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -68,7 +68,9 @@
 #endif
 
 MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t byte_count, int prot) {
-  CHECK_NE(0U, byte_count);
+  if (byte_count == 0) {
+    return new MemMap(name, NULL, 0, NULL, 0, prot);
+  }
   size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize);
   CheckMapRequest(addr, page_aligned_byte_count);
 
@@ -102,9 +104,11 @@
 
 MemMap* MemMap::MapFileAtAddress(byte* addr, size_t byte_count,
                                  int prot, int flags, int fd, off_t start, bool reuse) {
-  CHECK_NE(0U, byte_count);
   CHECK_NE(0, prot);
   CHECK_NE(0, flags & (MAP_SHARED | MAP_PRIVATE));
+  if (byte_count == 0) {
+    return new MemMap("file", NULL, 0, NULL, 0, prot);
+  }
   // Adjust 'offset' to be page-aligned as required by mmap.
   int page_offset = start % kPageSize;
   off_t page_aligned_offset = start - page_offset;
@@ -153,10 +157,15 @@
                size_t base_size, int prot)
     : name_(name), begin_(begin), size_(size), base_begin_(base_begin), base_size_(base_size),
       prot_(prot) {
-  CHECK(begin_ != NULL);
-  CHECK_NE(size_, 0U);
-  CHECK(base_begin_ != NULL);
-  CHECK_NE(base_size_, 0U);
+  if (size_ == 0) {
+    CHECK(begin_ == NULL);
+    CHECK(base_begin_ == NULL);
+    CHECK_EQ(base_size_, 0U);
+  } else {
+    CHECK(begin_ != NULL);
+    CHECK(base_begin_ != NULL);
+    CHECK_NE(base_size_, 0U);
+  }
 };
 
 void MemMap::UnMapAtEnd(byte* new_end) {
diff --git a/runtime/mem_map_test.cc b/runtime/mem_map_test.cc
new file mode 100644
index 0000000..dade01b
--- /dev/null
+++ b/runtime/mem_map_test.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mem_map.h"
+
+#include "UniquePtr.h"
+#include "gtest/gtest.h"
+
+namespace art {
+
+class MemMapTest : public testing::Test {};
+
+TEST_F(MemMapTest, MapAnonymousEmpty) {
+  UniquePtr<MemMap> map(MemMap::MapAnonymous("MapAnonymousEmpty",
+                                             NULL,
+                                             0,
+                                             PROT_READ));
+  ASSERT_TRUE(map.get() != NULL);
+}
+
+}  // namespace art