This patch moves the code reading /proc/self/environ into AsanGetEnv
in asan_linux.cc, because /proc is unavailable on Mac.
Instead the Mac version of AsanGetEnv iterates over the array of
environment variables obtained from _NSGetEnviron()



git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@148114 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index ab915a3..8a9b858 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -87,6 +87,7 @@
 // asan_linux.cc / asan_mac.cc
 void *AsanDoesNotSupportStaticLinkage();
 int AsanOpenReadonly(const char* filename);
+const char *AsanGetEnv(const char *name);
 
 void *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size);
 void *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size);
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index 17e2e37..8b05723 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -127,6 +127,34 @@
   return open(filename, O_RDONLY);
 }
 
+// Like getenv, but reads env directly from /proc and does not use libc.
+// This function should be called first inside __asan_init.
+const char* AsanGetEnv(const char* name) {
+  static char *environ;
+  static size_t len;
+  static bool inited;
+  if (!inited) {
+    inited = true;
+    size_t environ_size;
+    len = ReadFileToBuffer("/proc/self/environ",
+                           &environ, &environ_size, 1 << 20);
+  }
+  if (!environ || len == 0) return NULL;
+  size_t namelen = internal_strlen(name);
+  const char *p = environ;
+  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
+    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
+    const char* endp =
+        (char*)internal_memchr(p, '\0', len - (p - environ));
+    if (endp == NULL)  // this entry isn't NUL terminated
+      return NULL;
+    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
+      return p + namelen + 1;  // point after =
+    p = endp + 1;
+  }
+  return NULL;  // Not found.
+}
+
 size_t AsanRead(int fd, void *buf, size_t count) {
   return (size_t)syscall(__NR_read, fd, buf, count);
 }
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index 7efb0ef..4bfe74c 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -21,6 +21,7 @@
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
 
+#include <crt_externs.h>  // for _NSGetEnviron
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/ucontext.h>
@@ -114,6 +115,26 @@
   return open(filename, O_RDONLY);
 }
 
+const char *AsanGetEnv(const char *name) {
+  char ***env_ptr = _NSGetEnviron();
+  CHECK(env_ptr);
+  char **environ = *env_ptr;
+  CHECK(environ);
+  size_t name_len = internal_strlen(name);
+  while (*environ != NULL) {
+    size_t len = internal_strlen(*environ);
+    if (len > name_len) {
+      const char *p = *environ;
+      if (!internal_memcmp(p, name, name_len) &&
+          p[name_len] == '=') {  // Match.
+        return *environ + name_len + 1;  // String starting after =. 
+      }
+    }
+    environ++;
+  }
+  return NULL;
+}
+
 size_t AsanRead(int fd, void *buf, size_t count) {
   return read(fd, buf, count);
 }
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index 8944246..0036c76 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -91,34 +91,6 @@
   return read_len;
 }
 
-// Like getenv, but reads env directly from /proc and does not use libc.
-// This function should be called first inside __asan_init.
-static const char* GetEnvFromProcSelfEnviron(const char* name) {
-  static char *environ;
-  static size_t len;
-  static bool inited;
-  if (!inited) {
-    inited = true;
-    size_t environ_size;
-    len = ReadFileToBuffer("/proc/self/environ",
-                           &environ, &environ_size, 1 << 20);
-  }
-  if (!environ || len == 0) return NULL;
-  size_t namelen = internal_strlen(name);
-  const char *p = environ;
-  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
-    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
-    const char* endp =
-        (char*)internal_memchr(p, '\0', len - (p - environ));
-    if (endp == NULL)  // this entry isn't NUL terminated
-      return NULL;
-    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
-      return p + namelen + 1;  // point after =
-    p = endp + 1;
-  }
-  return NULL;  // Not found.
-}
-
 // ---------------------- mmap -------------------- {{{1
 void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) {
   Report("ERROR: AddressSanitizer failed to allocate "
@@ -397,7 +369,7 @@
   AsanDoesNotSupportStaticLinkage();
 
   // flags
-  const char *options = GetEnvFromProcSelfEnviron("ASAN_OPTIONS");
+  const char *options = AsanGetEnv("ASAN_OPTIONS");
   FLAG_malloc_context_size =
       IntFlagValue(options, "malloc_context_size=", kMallocContextSize);
   CHECK(FLAG_malloc_context_size <= kMallocContextSize);