Implement CheckMapRequest for Mac OS.

(cherry picked from commit d594adbd5126249950d42d3986ca86d066c3d912)

Change-Id: I1e99aa15d8fd9bde47042469fc31a3032b69bdf0
diff --git a/src/mem_map.cc b/src/mem_map.cc
index 92c6a59..885389d 100644
--- a/src/mem_map.cc
+++ b/src/mem_map.cc
@@ -29,7 +29,9 @@
 
 namespace art {
 
-size_t ParseHex(const std::string& string) {
+#if !defined(NDEBUG)
+
+static size_t ParseHex(const std::string& string) {
   CHECK_EQ(8U, string.size());
   const char* str = string.c_str();
   char* end;
@@ -39,17 +41,65 @@
   return value;
 }
 
+static void CheckMapRegion(uint32_t base, uint32_t limit, uint32_t start, uint32_t end, const std::string& maps) {
+  CHECK(!(base >= start && base < end)      // start of new within old
+        && !(limit > start && limit < end)  // end of new within old
+        && !(base <= start && limit > end)) // start/end of new includes all of old
+      << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
+                      base, limit, start, end)
+      << maps;
+}
+
 void CheckMapRequest(byte* addr, size_t length) {
-#if !defined(NDEBUG)
-#if defined(__APPLE__)
-  UNIMPLEMENTED(WARNING);
-#else
   if (addr == NULL) {
     return;
   }
-  size_t base = reinterpret_cast<size_t>(addr);
-  size_t limit = base + length;
+  uint32_t base = reinterpret_cast<size_t>(addr);
+  uint32_t limit = base + length;
 
+#if defined(__APPLE__)
+  // Mac OS vmmap(1) output currently looks something like this:
+
+  // Virtual Memory Map of process 51036 (dex2oatd)
+  // Output report format:  2.2  -- 32-bit process
+  //
+  // ==== regions for process 51036  (non-writable and writable regions are interleaved)
+  // __PAGEZERO             00000000-00001000 [    4K     0K     0K] ---/--- SM=NUL          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00001000-00015000 [   80K    80K     0K] r-x/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __DATA                 00015000-00016000 [    4K     4K     4K] rw-/rwx SM=PRV          out/host/darwin-x86/bin/dex2oatd
+  // __LINKEDIT             00016000-00044000 [  184K   184K     0K] r--/rwx SM=COW          out/host/darwin-x86/bin/dex2oatd
+  // __TEXT                 00044000-00046000 [    8K     8K     4K] r-x/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __DATA                 00046000-00047000 [    4K     4K     4K] rw-/rwx SM=ZER          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // __LINKEDIT             00047000-0004a000 [   12K    12K     0K] r--/rwx SM=COW          out/host/darwin-x86/obj/lib/libnativehelper.dylib
+  // ...
+
+  std::string command(StringPrintf("vmmap -v -interleaved %d", getpid()));
+  FILE* fp = popen(command.c_str(), "r");
+  if (fp == NULL) {
+    PLOG(FATAL) << "popen failed";
+  }
+  std::vector<char> chars(512);
+  std::string maps;
+  while (fgets(&chars[0], chars.size(), fp) != NULL) {
+    std::string line(&chars[0]);
+    maps += line;
+    if (line.size() < 40 || line[31] != '-') {
+      continue;
+    }
+
+    std::string start_str(line.substr(22, 8));
+    std::string end_str(line.substr(31, 8));
+    uint32_t start = ParseHex(start_str);
+    uint32_t end = ParseHex(end_str);
+    CheckMapRegion(base, limit, start, end, maps);
+  }
+  if (ferror(fp)) {
+    PLOG(FATAL) << "fgets failed";
+  }
+  if (pclose(fp) == -1) {
+    PLOG(FATAL) << "pclose failed";
+  }
+#else // Linux
   std::string maps;
   bool read = ReadFileToString("/proc/self/maps", &maps);
   if (!read) {
@@ -93,20 +143,18 @@
     std::string end_str(maps.substr(i+1+8, 8));
     uint32_t start = ParseHex(start_str);
     uint32_t end = ParseHex(end_str);
-    CHECK(!(base >= start && base < end)       // start of new within old
-          && !(limit > start && limit < end)  // end of new within old
-          && !(base <= start && limit > end))  // start/end of new includes all of old
-        << StringPrintf("Requested region %08x-%08x overlaps with existing map %08x-%08x\n",
-                        base, limit, start, end)
-        << maps;
+    CheckMapRegion(base, limit, start, end, maps);
     i += 8+1+8;
     i = maps.find('\n', i);
     CHECK(i != std::string::npos) << "Failed to find newline from pos " << i << "\n" << maps;
   }
 #endif
-#endif
 }
 
+#else
+static void CheckMapRequest(byte* addr, size_t length) { }
+#endif
+
 MemMap* MemMap::MapAnonymous(const char* name, byte* addr, size_t length, int prot) {
   CHECK_NE(0U, length);
   CHECK_NE(0, prot);