[llvm-commits] [compiler-rt] r148385 - in /compiler-rt/trunk/lib/asan: asan_internal.h asan_linux.cc asan_mac.cc asan_procmaps.h

Alexander Potapenko glider at google.com
Wed Jan 18 03:16:05 PST 2012


Author: glider
Date: Wed Jan 18 05:16:05 2012
New Revision: 148385

URL: http://llvm.org/viewvc/llvm-project?rev=148385&view=rev
Log:
Implement AsanProcMaps for Mac OS. The code from sysinfo/ is not needed anymore and should be cleaned up.

Modified:
    compiler-rt/trunk/lib/asan/asan_internal.h
    compiler-rt/trunk/lib/asan/asan_linux.cc
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_procmaps.h

Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=148385&r1=148384&r2=148385&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Wed Jan 18 05:16:05 2012
@@ -43,7 +43,8 @@
 #ifdef __linux__
 # define ASAN_USE_SYSINFO 0
 #else
-# define ASAN_USE_SYSINFO 1
+// TODO(glider): clean up sysinfo.
+# define ASAN_USE_SYSINFO 0
 #endif
 #endif
 

Modified: compiler-rt/trunk/lib/asan/asan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_linux.cc?rev=148385&r1=148384&r2=148385&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_linux.cc Wed Jan 18 05:16:05 2012
@@ -220,17 +220,7 @@
 bool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
                                           char filename[],
                                           size_t filename_size) {
-  AsanProcMaps proc_maps;
-  uintptr_t start, end, file_offset;
-  while (proc_maps.Next(&start, &end, &file_offset, filename, filename_size)) {
-    if (addr >= start && addr < end) {
-      *offset = (addr - start) + file_offset;
-      return true;
-    }
-  }
-  if (filename_size)
-    filename[0] = '\0';
-  return false;
+  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
 }
 
 #else  // __arm__

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=148385&r1=148384&r2=148385&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Wed Jan 18 05:16:05 2012
@@ -17,11 +17,13 @@
 #include "asan_mac.h"
 
 #include "asan_internal.h"
+#include "asan_procmaps.h"
 #include "asan_stack.h"
 #include "asan_thread.h"
 #include "asan_thread_registry.h"
 
 #include <crt_externs.h>  // for _NSGetEnviron
+#include <mach-o/dyld.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/ucontext.h>
@@ -145,6 +147,94 @@
   return close(fd);
 }
 
+AsanProcMaps::AsanProcMaps() {
+  Reset();
+}
+
+AsanProcMaps::~AsanProcMaps() {
+}
+
+void AsanProcMaps::Reset() {
+  // Count down from the top.
+  // TODO(glider): as per man 3 dyld, iterating over the headers with
+  // _dyld_image_count is thread-unsafe.
+  current_image_ = _dyld_image_count();
+  current_load_cmd_ = -1;
+}
+
+// Similar code is used in Google Perftools,
+// http://code.google.com/p/google-perftools.
+template<uint32_t kMagic, uint32_t kLCSegment,
+         typename MachHeader, typename SegmentCommand>
+static bool NextExtMachHelper(const mach_header* hdr,
+                              int current_image, int current_load_cmd,
+                              uintptr_t *start, uintptr_t *end,
+                              uintptr_t *offset,
+                              char filename[], size_t filename_size) {
+  if (hdr->magic != kMagic)
+    return false;
+  const char* lc = (const char *)hdr + sizeof(MachHeader);
+  // TODO(csilvers): make this not-quadradic (increment and hold state)
+  for (int j = 0; j < current_load_cmd; j++)  // advance to *our* load_cmd
+    lc += ((const load_command *)lc)->cmdsize;
+  if (((const load_command *)lc)->cmd == kLCSegment) {
+    const intptr_t 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) *offset = sc->fileoff;
+    if (filename) {
+      real_strncpy(filename, _dyld_get_image_name(current_image),
+                   filename_size);
+    }
+    return true;
+  }
+  return false;
+}
+
+bool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end,
+                        uintptr_t *offset, char filename[],
+                        size_t filename_size) {
+  // We return a separate entry for each segment in the DLL. (TODO(csilvers):
+  // can we do better?)  A DLL ("image") has load-commands, some of which
+  // talk about segment boundaries.
+  // cf image_for_address from http://svn.digium.com/view/asterisk/team/oej/minivoicemail/dlfcn.c?revision=53912
+  for (; current_image_ >= 0; current_image_--) {
+    const mach_header* hdr = _dyld_get_image_header(current_image_);
+    if (!hdr) continue;
+    if (current_load_cmd_ < 0)   // set up for this image
+      current_load_cmd_ = hdr->ncmds;  // again, go from the top down
+
+    // We start with the next load command (we've already looked at this one).
+    for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) {
+#ifdef MH_MAGIC_64
+      if (NextExtMachHelper<MH_MAGIC_64, LC_SEGMENT_64,
+                            struct mach_header_64, struct segment_command_64>(
+                                hdr, current_image_, current_load_cmd_,
+                                start, end, offset, filename, filename_size)) {
+        return true;
+      }
+#endif
+      if (NextExtMachHelper<MH_MAGIC, LC_SEGMENT,
+                            struct mach_header, struct segment_command>(
+                                hdr, current_image_, current_load_cmd_,
+                                start, end, offset, filename, filename_size)) {
+        return true;
+      }
+    }
+    // If we get here, no more load_cmd's in this image talk about
+    // segments.  Go on to the next image.
+  }
+  // We didn't find anything.
+  return false;
+}
+
+bool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
+                                          char filename[],
+                                          size_t filename_size) {
+  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
+}
+
 void AsanThread::SetThreadStackTopAndBottom() {
   size_t stacksize = pthread_get_stacksize_np(pthread_self());
   void *stackaddr = pthread_get_stackaddr_np(pthread_self());
@@ -154,7 +244,6 @@
   CHECK(AddrIsInStack((uintptr_t)&local));
 }
 
-
 AsanLock::AsanLock(LinkerInitialized) {
   // We assume that OS_SPINLOCK_INIT is zero
 }

Modified: compiler-rt/trunk/lib/asan/asan_procmaps.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_procmaps.h?rev=148385&r1=148384&r2=148385&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_procmaps.h (original)
+++ compiler-rt/trunk/lib/asan/asan_procmaps.h Wed Jan 18 05:16:05 2012
@@ -30,13 +30,33 @@
                               char filename[], size_t filename_size);
   ~AsanProcMaps();
  private:
+  // Default implementation of GetObjectNameAndOffset.
+  // Quite slow, because it iterates through the whole process map for each
+  // lookup.
+  bool IterateForObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
+                                     char filename[], size_t filename_size) {
+    AsanProcMaps proc_maps;
+    uintptr_t start, end, file_offset;
+    while (proc_maps.Next(&start, &end, &file_offset,
+                          filename, filename_size)) {
+      if (addr >= start && addr < end) {
+        *offset = (addr - start) + file_offset;
+        return true;
+      }
+    }
+    if (filename_size)
+      filename[0] = '\0';
+    return false;
+  }
+
 #if defined __linux__
   char *proc_self_maps_buff_;
   size_t proc_self_maps_buff_mmaped_size_;
   size_t proc_self_maps_buff_len_;
   char *current_;
 #elif defined __APPLE__
-// FIXME: Mac code goes here
+  int current_image_;
+  int current_load_cmd_;
 #endif
 };
 





More information about the llvm-commits mailing list