[compiler-rt] r198003 - [Sanitizer] Move OS-specific code for MemoryMappingLayout into separate source files.

Alexey Samsonov samsonov at google.com
Wed Dec 25 00:01:17 PST 2013


Author: samsonov
Date: Wed Dec 25 02:01:16 2013
New Revision: 198003

URL: http://llvm.org/viewvc/llvm-project?rev=198003&view=rev
Log:
[Sanitizer] Move OS-specific code for MemoryMappingLayout into separate source files.

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_posix.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h

Modified: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt?rev=198003&r1=198002&r2=198003&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt Wed Dec 25 02:01:16 2013
@@ -14,6 +14,9 @@ set(SANITIZER_SOURCES
   sanitizer_platform_limits_posix.cc
   sanitizer_posix.cc
   sanitizer_printf.cc
+  sanitizer_procmaps_linux.cc
+  sanitizer_procmaps_mac.cc
+  sanitizer_procmaps_posix.cc
   sanitizer_stackdepot.cc
   sanitizer_stacktrace.cc
   sanitizer_suppressions.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=198003&r1=198002&r2=198003&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Wed Dec 25 02:01:16 2013
@@ -318,213 +318,6 @@ void PrepareForSandboxing() {
 #endif
 }
 
-// ----------------- sanitizer_procmaps.h
-// Linker initialized.
-ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
-StaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
-
-MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
-  proc_self_maps_.len =
-      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
-                       &proc_self_maps_.mmaped_size, 1 << 26);
-  if (cache_enabled) {
-    if (proc_self_maps_.mmaped_size == 0) {
-      LoadFromCache();
-      CHECK_GT(proc_self_maps_.len, 0);
-    }
-  } else {
-    CHECK_GT(proc_self_maps_.mmaped_size, 0);
-  }
-  Reset();
-  // FIXME: in the future we may want to cache the mappings on demand only.
-  if (cache_enabled)
-    CacheMemoryMappings();
-}
-
-MemoryMappingLayout::~MemoryMappingLayout() {
-  // Only unmap the buffer if it is different from the cached one. Otherwise
-  // it will be unmapped when the cache is refreshed.
-  if (proc_self_maps_.data != cached_proc_self_maps_.data) {
-    UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
-  }
-}
-
-void MemoryMappingLayout::Reset() {
-  current_ = proc_self_maps_.data;
-}
-
-// static
-void MemoryMappingLayout::CacheMemoryMappings() {
-  SpinMutexLock l(&cache_lock_);
-  // Don't invalidate the cache if the mappings are unavailable.
-  ProcSelfMapsBuff old_proc_self_maps;
-  old_proc_self_maps = cached_proc_self_maps_;
-  cached_proc_self_maps_.len =
-      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
-                       &cached_proc_self_maps_.mmaped_size, 1 << 26);
-  if (cached_proc_self_maps_.mmaped_size == 0) {
-    cached_proc_self_maps_ = old_proc_self_maps;
-  } else {
-    if (old_proc_self_maps.mmaped_size) {
-      UnmapOrDie(old_proc_self_maps.data,
-                 old_proc_self_maps.mmaped_size);
-    }
-  }
-}
-
-void MemoryMappingLayout::LoadFromCache() {
-  SpinMutexLock l(&cache_lock_);
-  if (cached_proc_self_maps_.data) {
-    proc_self_maps_ = cached_proc_self_maps_;
-  }
-}
-
-// Parse a hex value in str and update str.
-static uptr ParseHex(char **str) {
-  uptr x = 0;
-  char *s;
-  for (s = *str; ; s++) {
-    char c = *s;
-    uptr v = 0;
-    if (c >= '0' && c <= '9')
-      v = c - '0';
-    else if (c >= 'a' && c <= 'f')
-      v = c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      v = c - 'A' + 10;
-    else
-      break;
-    x = x * 16 + v;
-  }
-  *str = s;
-  return x;
-}
-
-static bool IsOneOf(char c, char c1, char c2) {
-  return c == c1 || c == c2;
-}
-
-static bool IsDecimal(char c) {
-  return c >= '0' && c <= '9';
-}
-
-static bool IsHex(char c) {
-  return (c >= '0' && c <= '9')
-      || (c >= 'a' && c <= 'f');
-}
-
-static uptr ReadHex(const char *p) {
-  uptr v = 0;
-  for (; IsHex(p[0]); p++) {
-    if (p[0] >= '0' && p[0] <= '9')
-      v = v * 16 + p[0] - '0';
-    else
-      v = v * 16 + p[0] - 'a' + 10;
-  }
-  return v;
-}
-
-static uptr ReadDecimal(const char *p) {
-  uptr v = 0;
-  for (; IsDecimal(p[0]); p++)
-    v = v * 10 + p[0] - '0';
-  return v;
-}
-
-
-bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
-                               char filename[], uptr filename_size,
-                               uptr *protection) {
-  char *last = proc_self_maps_.data + proc_self_maps_.len;
-  if (current_ >= last) return false;
-  uptr dummy;
-  if (!start) start = &dummy;
-  if (!end) end = &dummy;
-  if (!offset) offset = &dummy;
-  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
-  if (next_line == 0)
-    next_line = last;
-  // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
-  *start = ParseHex(&current_);
-  CHECK_EQ(*current_++, '-');
-  *end = ParseHex(&current_);
-  CHECK_EQ(*current_++, ' ');
-  uptr local_protection = 0;
-  CHECK(IsOneOf(*current_, '-', 'r'));
-  if (*current_++ == 'r')
-    local_protection |= kProtectionRead;
-  CHECK(IsOneOf(*current_, '-', 'w'));
-  if (*current_++ == 'w')
-    local_protection |= kProtectionWrite;
-  CHECK(IsOneOf(*current_, '-', 'x'));
-  if (*current_++ == 'x')
-    local_protection |= kProtectionExecute;
-  CHECK(IsOneOf(*current_, 's', 'p'));
-  if (*current_++ == 's')
-    local_protection |= kProtectionShared;
-  if (protection) {
-    *protection = local_protection;
-  }
-  CHECK_EQ(*current_++, ' ');
-  *offset = ParseHex(&current_);
-  CHECK_EQ(*current_++, ' ');
-  ParseHex(&current_);
-  CHECK_EQ(*current_++, ':');
-  ParseHex(&current_);
-  CHECK_EQ(*current_++, ' ');
-  while (IsDecimal(*current_))
-    current_++;
-  // Qemu may lack the trailing space.
-  // http://code.google.com/p/address-sanitizer/issues/detail?id=160
-  // CHECK_EQ(*current_++, ' ');
-  // Skip spaces.
-  while (current_ < next_line && *current_ == ' ')
-    current_++;
-  // Fill in the filename.
-  uptr i = 0;
-  while (current_ < next_line) {
-    if (filename && i < filename_size - 1)
-      filename[i++] = *current_;
-    current_++;
-  }
-  if (filename && i < filename_size)
-    filename[i] = 0;
-  current_ = next_line + 1;
-  return true;
-}
-
-// Gets the object name and the offset by walking MemoryMappingLayout.
-bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
-                                                 char filename[],
-                                                 uptr filename_size,
-                                                 uptr *protection) {
-  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
-                                       protection);
-}
-
-void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
-  char *smaps = 0;
-  uptr smaps_cap = 0;
-  uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
-      &smaps, &smaps_cap, 64<<20);
-  uptr start = 0;
-  bool file = false;
-  const char *pos = smaps;
-  while (pos < smaps + smaps_len) {
-    if (IsHex(pos[0])) {
-      start = ReadHex(pos);
-      for (; *pos != '/' && *pos > '\n'; pos++) {}
-      file = *pos == '/';
-    } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
-      for (; *pos < '0' || *pos > '9'; pos++) {}
-      uptr rss = ReadDecimal(pos) * 1024;
-      cb(start, rss, file, stats, stats_size);
-    }
-    while (*pos++ != '\n') {}
-  }
-  UnmapOrDie(smaps, smaps_cap);
-}
-
 enum MutexState {
   MtxUnlocked = 0,
   MtxLocked = 1,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=198003&r1=198002&r2=198003&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Wed Dec 25 02:01:16 2013
@@ -30,8 +30,6 @@
 
 #include <crt_externs.h>  // for _NSGetEnviron
 #include <fcntl.h>
-#include <mach-o/dyld.h>
-#include <mach-o/loader.h>
 #include <pthread.h>
 #include <sched.h>
 #include <sys/mman.h>
@@ -179,148 +177,6 @@ uptr GetPageSize() {
   return sysconf(_SC_PAGESIZE);
 }
 
-// ----------------- sanitizer_procmaps.h
-
-MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
-  Reset();
-}
-
-MemoryMappingLayout::~MemoryMappingLayout() {
-}
-
-// More information about Mach-O headers can be found in mach-o/loader.h
-// Each Mach-O image has a header (mach_header or mach_header_64) starting with
-// a magic number, and a list of linker load commands directly following the
-// header.
-// A load command is at least two 32-bit words: the command type and the
-// command size in bytes. We're interested only in segment load commands
-// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
-// into the task's address space.
-// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
-// segment_command_64 correspond to the memory address, memory size and the
-// file offset of the current memory segment.
-// Because these fields are taken from the images as is, one needs to add
-// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
-
-void MemoryMappingLayout::Reset() {
-  // Count down from the top.
-  // TODO(glider): as per man 3 dyld, iterating over the headers with
-  // _dyld_image_count is thread-unsafe. We need to register callbacks for
-  // adding and removing images which will invalidate the MemoryMappingLayout
-  // state.
-  current_image_ = _dyld_image_count();
-  current_load_cmd_count_ = -1;
-  current_load_cmd_addr_ = 0;
-  current_magic_ = 0;
-  current_filetype_ = 0;
-}
-
-// static
-void MemoryMappingLayout::CacheMemoryMappings() {
-  // No-op on Mac for now.
-}
-
-void MemoryMappingLayout::LoadFromCache() {
-  // No-op on Mac for now.
-}
-
-// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
-// Google Perftools, http://code.google.com/p/google-perftools.
-
-// NextSegmentLoad scans the current image for the next segment load command
-// and returns the start and end addresses and file offset of the corresponding
-// segment.
-// Note that the segment addresses are not necessarily sorted.
-template<u32 kLCSegment, typename SegmentCommand>
-bool MemoryMappingLayout::NextSegmentLoad(
-    uptr *start, uptr *end, uptr *offset,
-    char filename[], uptr filename_size, uptr *protection) {
-  if (protection)
-    UNIMPLEMENTED();
-  const char* lc = current_load_cmd_addr_;
-  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
-  if (((const load_command *)lc)->cmd == kLCSegment) {
-    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
-    const SegmentCommand* sc = (const SegmentCommand *)lc;
-    if (start) *start = sc->vmaddr + dlloff;
-    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
-    if (offset) {
-      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
-        *offset = sc->vmaddr;
-      } else {
-        *offset = sc->fileoff;
-      }
-    }
-    if (filename) {
-      internal_strncpy(filename, _dyld_get_image_name(current_image_),
-                       filename_size);
-    }
-    return true;
-  }
-  return false;
-}
-
-bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
-                               char filename[], uptr filename_size,
-                               uptr *protection) {
-  for (; current_image_ >= 0; current_image_--) {
-    const mach_header* hdr = _dyld_get_image_header(current_image_);
-    if (!hdr) continue;
-    if (current_load_cmd_count_ < 0) {
-      // Set up for this image;
-      current_load_cmd_count_ = hdr->ncmds;
-      current_magic_ = hdr->magic;
-      current_filetype_ = hdr->filetype;
-      switch (current_magic_) {
-#ifdef MH_MAGIC_64
-        case MH_MAGIC_64: {
-          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
-          break;
-        }
-#endif
-        case MH_MAGIC: {
-          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
-          break;
-        }
-        default: {
-          continue;
-        }
-      }
-    }
-
-    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
-      switch (current_magic_) {
-        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
-#ifdef MH_MAGIC_64
-        case MH_MAGIC_64: {
-          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
-                  start, end, offset, filename, filename_size, protection))
-            return true;
-          break;
-        }
-#endif
-        case MH_MAGIC: {
-          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
-                  start, end, offset, filename, filename_size, protection))
-            return true;
-          break;
-        }
-      }
-    }
-    // If we get here, no more load_cmd's in this image talk about
-    // segments.  Go on to the next image.
-  }
-  return false;
-}
-
-bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
-                                                 char filename[],
-                                                 uptr filename_size,
-                                                 uptr *protection) {
-  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
-                                       protection);
-}
-
 BlockingMutex::BlockingMutex(LinkerInitialized) {
   // We assume that OS_SPINLOCK_INIT is zero
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=198003&r1=198002&r2=198003&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h Wed Dec 25 02:01:16 2013
@@ -71,33 +71,10 @@ class MemoryMappingLayout {
   // lookup.
   bool IterateForObjectNameAndOffset(uptr addr, uptr *offset,
                                      char filename[], uptr filename_size,
-                                     uptr *protection) {
-    Reset();
-    uptr start, end, file_offset;
-    for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
-                         protection);
-         i++) {
-      if (addr >= start && addr < end) {
-        // Don't subtract 'start' for the first entry:
-        // * If a binary is compiled w/o -pie, then the first entry in
-        //   process maps is likely the binary itself (all dynamic libs
-        //   are mapped higher in address space). For such a binary,
-        //   instruction offset in binary coincides with the actual
-        //   instruction address in virtual memory (as code section
-        //   is mapped to a fixed memory range).
-        // * If a binary is compiled with -pie, all the modules are
-        //   mapped high at address space (in particular, higher than
-        //   shadow memory of the tool), so the module can't be the
-        //   first entry.
-        *offset = (addr - (i ? start : 0)) + file_offset;
-        return true;
-      }
-    }
-    if (filename_size)
-      filename[0] = '\0';
-    return false;
-  }
+                                     uptr *protection);
 
+  // FIXME: Hide implementation details for different platforms in
+  // platform-specific files.
 # if SANITIZER_LINUX
   ProcSelfMapsBuff proc_self_maps_;
   char *current_;

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc?rev=198003&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc Wed Dec 25 02:01:16 2013
@@ -0,0 +1,227 @@
+//===-- sanitizer_procmaps_linux.cc ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Linux-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+#include "sanitizer_common.h"
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+// Linker initialized.
+ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
+StaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+  proc_self_maps_.len =
+      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
+                       &proc_self_maps_.mmaped_size, 1 << 26);
+  if (cache_enabled) {
+    if (proc_self_maps_.mmaped_size == 0) {
+      LoadFromCache();
+      CHECK_GT(proc_self_maps_.len, 0);
+    }
+  } else {
+    CHECK_GT(proc_self_maps_.mmaped_size, 0);
+  }
+  Reset();
+  // FIXME: in the future we may want to cache the mappings on demand only.
+  if (cache_enabled)
+    CacheMemoryMappings();
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+  // Only unmap the buffer if it is different from the cached one. Otherwise
+  // it will be unmapped when the cache is refreshed.
+  if (proc_self_maps_.data != cached_proc_self_maps_.data) {
+    UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
+  }
+}
+
+void MemoryMappingLayout::Reset() {
+  current_ = proc_self_maps_.data;
+}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+  SpinMutexLock l(&cache_lock_);
+  // Don't invalidate the cache if the mappings are unavailable.
+  ProcSelfMapsBuff old_proc_self_maps;
+  old_proc_self_maps = cached_proc_self_maps_;
+  cached_proc_self_maps_.len =
+      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
+                       &cached_proc_self_maps_.mmaped_size, 1 << 26);
+  if (cached_proc_self_maps_.mmaped_size == 0) {
+    cached_proc_self_maps_ = old_proc_self_maps;
+  } else {
+    if (old_proc_self_maps.mmaped_size) {
+      UnmapOrDie(old_proc_self_maps.data,
+                 old_proc_self_maps.mmaped_size);
+    }
+  }
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+  SpinMutexLock l(&cache_lock_);
+  if (cached_proc_self_maps_.data) {
+    proc_self_maps_ = cached_proc_self_maps_;
+  }
+}
+
+// Parse a hex value in str and update str.
+static uptr ParseHex(char **str) {
+  uptr x = 0;
+  char *s;
+  for (s = *str; ; s++) {
+    char c = *s;
+    uptr v = 0;
+    if (c >= '0' && c <= '9')
+      v = c - '0';
+    else if (c >= 'a' && c <= 'f')
+      v = c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      v = c - 'A' + 10;
+    else
+      break;
+    x = x * 16 + v;
+  }
+  *str = s;
+  return x;
+}
+
+static bool IsOneOf(char c, char c1, char c2) {
+  return c == c1 || c == c2;
+}
+
+static bool IsDecimal(char c) {
+  return c >= '0' && c <= '9';
+}
+
+static bool IsHex(char c) {
+  return (c >= '0' && c <= '9')
+      || (c >= 'a' && c <= 'f');
+}
+
+static uptr ReadHex(const char *p) {
+  uptr v = 0;
+  for (; IsHex(p[0]); p++) {
+    if (p[0] >= '0' && p[0] <= '9')
+      v = v * 16 + p[0] - '0';
+    else
+      v = v * 16 + p[0] - 'a' + 10;
+  }
+  return v;
+}
+
+static uptr ReadDecimal(const char *p) {
+  uptr v = 0;
+  for (; IsDecimal(p[0]); p++)
+    v = v * 10 + p[0] - '0';
+  return v;
+}
+
+bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
+                               char filename[], uptr filename_size,
+                               uptr *protection) {
+  char *last = proc_self_maps_.data + proc_self_maps_.len;
+  if (current_ >= last) return false;
+  uptr dummy;
+  if (!start) start = &dummy;
+  if (!end) end = &dummy;
+  if (!offset) offset = &dummy;
+  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
+  if (next_line == 0)
+    next_line = last;
+  // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
+  *start = ParseHex(&current_);
+  CHECK_EQ(*current_++, '-');
+  *end = ParseHex(&current_);
+  CHECK_EQ(*current_++, ' ');
+  uptr local_protection = 0;
+  CHECK(IsOneOf(*current_, '-', 'r'));
+  if (*current_++ == 'r')
+    local_protection |= kProtectionRead;
+  CHECK(IsOneOf(*current_, '-', 'w'));
+  if (*current_++ == 'w')
+    local_protection |= kProtectionWrite;
+  CHECK(IsOneOf(*current_, '-', 'x'));
+  if (*current_++ == 'x')
+    local_protection |= kProtectionExecute;
+  CHECK(IsOneOf(*current_, 's', 'p'));
+  if (*current_++ == 's')
+    local_protection |= kProtectionShared;
+  if (protection) {
+    *protection = local_protection;
+  }
+  CHECK_EQ(*current_++, ' ');
+  *offset = ParseHex(&current_);
+  CHECK_EQ(*current_++, ' ');
+  ParseHex(&current_);
+  CHECK_EQ(*current_++, ':');
+  ParseHex(&current_);
+  CHECK_EQ(*current_++, ' ');
+  while (IsDecimal(*current_))
+    current_++;
+  // Qemu may lack the trailing space.
+  // http://code.google.com/p/address-sanitizer/issues/detail?id=160
+  // CHECK_EQ(*current_++, ' ');
+  // Skip spaces.
+  while (current_ < next_line && *current_ == ' ')
+    current_++;
+  // Fill in the filename.
+  uptr i = 0;
+  while (current_ < next_line) {
+    if (filename && i < filename_size - 1)
+      filename[i++] = *current_;
+    current_++;
+  }
+  if (filename && i < filename_size)
+    filename[i] = 0;
+  current_ = next_line + 1;
+  return true;
+}
+
+// Gets the object name and the offset by walking MemoryMappingLayout.
+bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
+                                                 char filename[],
+                                                 uptr filename_size,
+                                                 uptr *protection) {
+  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
+                                       protection);
+}
+
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
+  char *smaps = 0;
+  uptr smaps_cap = 0;
+  uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
+      &smaps, &smaps_cap, 64<<20);
+  uptr start = 0;
+  bool file = false;
+  const char *pos = smaps;
+  while (pos < smaps + smaps_len) {
+    if (IsHex(pos[0])) {
+      start = ReadHex(pos);
+      for (; *pos != '/' && *pos > '\n'; pos++) {}
+      file = *pos == '/';
+    } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
+      for (; *pos < '0' || *pos > '9'; pos++) {}
+      uptr rss = ReadDecimal(pos) * 1024;
+      cb(start, rss, file, stats, stats_size);
+    }
+    while (*pos++ != '\n') {}
+  }
+  UnmapOrDie(smaps, smaps_cap);
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_LINUX

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc?rev=198003&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc Wed Dec 25 02:01:16 2013
@@ -0,0 +1,165 @@
+//===-- sanitizer_procmaps_mac.cc -----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings (Mac-specific parts).
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+#include "sanitizer_common.h"
+#include "sanitizer_procmaps.h"
+
+#include <mach-o/dyld.h>
+#include <mach-o/loader.h>
+
+namespace __sanitizer {
+
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
+  Reset();
+}
+
+MemoryMappingLayout::~MemoryMappingLayout() {
+}
+
+// More information about Mach-O headers can be found in mach-o/loader.h
+// Each Mach-O image has a header (mach_header or mach_header_64) starting with
+// a magic number, and a list of linker load commands directly following the
+// header.
+// A load command is at least two 32-bit words: the command type and the
+// command size in bytes. We're interested only in segment load commands
+// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
+// into the task's address space.
+// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
+// segment_command_64 correspond to the memory address, memory size and the
+// file offset of the current memory segment.
+// Because these fields are taken from the images as is, one needs to add
+// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
+
+void MemoryMappingLayout::Reset() {
+  // Count down from the top.
+  // TODO(glider): as per man 3 dyld, iterating over the headers with
+  // _dyld_image_count is thread-unsafe. We need to register callbacks for
+  // adding and removing images which will invalidate the MemoryMappingLayout
+  // state.
+  current_image_ = _dyld_image_count();
+  current_load_cmd_count_ = -1;
+  current_load_cmd_addr_ = 0;
+  current_magic_ = 0;
+  current_filetype_ = 0;
+}
+
+// static
+void MemoryMappingLayout::CacheMemoryMappings() {
+  // No-op on Mac for now.
+}
+
+void MemoryMappingLayout::LoadFromCache() {
+  // No-op on Mac for now.
+}
+
+// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
+// Google Perftools, http://code.google.com/p/google-perftools.
+
+// NextSegmentLoad scans the current image for the next segment load command
+// and returns the start and end addresses and file offset of the corresponding
+// segment.
+// Note that the segment addresses are not necessarily sorted.
+template<u32 kLCSegment, typename SegmentCommand>
+bool MemoryMappingLayout::NextSegmentLoad(
+    uptr *start, uptr *end, uptr *offset,
+    char filename[], uptr filename_size, uptr *protection) {
+  if (protection)
+    UNIMPLEMENTED();
+  const char* lc = current_load_cmd_addr_;
+  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
+  if (((const load_command *)lc)->cmd == kLCSegment) {
+    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
+    const SegmentCommand* sc = (const SegmentCommand *)lc;
+    if (start) *start = sc->vmaddr + dlloff;
+    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
+    if (offset) {
+      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
+        *offset = sc->vmaddr;
+      } else {
+        *offset = sc->fileoff;
+      }
+    }
+    if (filename) {
+      internal_strncpy(filename, _dyld_get_image_name(current_image_),
+                       filename_size);
+    }
+    return true;
+  }
+  return false;
+}
+
+bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
+                               char filename[], uptr filename_size,
+                               uptr *protection) {
+  for (; current_image_ >= 0; current_image_--) {
+    const mach_header* hdr = _dyld_get_image_header(current_image_);
+    if (!hdr) continue;
+    if (current_load_cmd_count_ < 0) {
+      // Set up for this image;
+      current_load_cmd_count_ = hdr->ncmds;
+      current_magic_ = hdr->magic;
+      current_filetype_ = hdr->filetype;
+      switch (current_magic_) {
+#ifdef MH_MAGIC_64
+        case MH_MAGIC_64: {
+          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
+          break;
+        }
+#endif
+        case MH_MAGIC: {
+          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
+          break;
+        }
+        default: {
+          continue;
+        }
+      }
+    }
+
+    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
+      switch (current_magic_) {
+        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
+#ifdef MH_MAGIC_64
+        case MH_MAGIC_64: {
+          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
+                  start, end, offset, filename, filename_size, protection))
+            return true;
+          break;
+        }
+#endif
+        case MH_MAGIC: {
+          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
+                  start, end, offset, filename, filename_size, protection))
+            return true;
+          break;
+        }
+      }
+    }
+    // If we get here, no more load_cmd's in this image talk about
+    // segments.  Go on to the next image.
+  }
+  return false;
+}
+
+bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
+                                                 char filename[],
+                                                 uptr filename_size,
+                                                 uptr *protection) {
+  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
+                                       protection);
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_MAC

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_posix.cc?rev=198003&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_posix.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_posix.cc Wed Dec 25 02:01:16 2013
@@ -0,0 +1,51 @@
+//===-- sanitizer_procmaps_posix.cc ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Information about the process mappings.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_POSIX
+#include "sanitizer_procmaps.h"
+
+namespace __sanitizer {
+
+bool MemoryMappingLayout::IterateForObjectNameAndOffset(uptr addr, uptr *offset,
+                                                        char filename[],
+                                                        uptr filename_size,
+                                                        uptr *protection) {
+  Reset();
+  uptr start, end, file_offset;
+  for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
+                       protection);
+       i++) {
+    if (addr >= start && addr < end) {
+      // Don't subtract 'start' for the first entry:
+      // * If a binary is compiled w/o -pie, then the first entry in
+      //   process maps is likely the binary itself (all dynamic libs
+      //   are mapped higher in address space). For such a binary,
+      //   instruction offset in binary coincides with the actual
+      //   instruction address in virtual memory (as code section
+      //   is mapped to a fixed memory range).
+      // * If a binary is compiled with -pie, all the modules are
+      //   mapped high at address space (in particular, higher than
+      //   shadow memory of the tool), so the module can't be the
+      //   first entry.
+      *offset = (addr - (i ? start : 0)) + file_offset;
+      return true;
+    }
+  }
+  if (filename_size)
+    filename[0] = '\0';
+  return false;
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_POSIX





More information about the llvm-commits mailing list