<div style="font-family: arial, helvetica, sans-serif; font-size: 10pt"><br><br><div class="gmail_quote">On Sat, Dec 1, 2012 at 6:53 AM, Alexey Samsonov <span dir="ltr"><<a href="mailto:samsonov@google.com" target="_blank">samsonov@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-family:arial,helvetica,sans-serif;font-size:10pt"><br><br><div class="gmail_quote"><div><div class="h5">
On Fri, Nov 30, 2012 at 6:39 PM, Alexander Potapenko <span dir="ltr"><<a href="mailto:glider@google.com" target="_blank">glider@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: glider<br>
Date: Fri Nov 30 20:39:45 2012<br>
New Revision: <a href="tel:169076" value="+49169076" target="_blank">169076</a><br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=169076&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=169076&view=rev</a><br>
Log:<br>
Add caching to the MemoryMappingLayout class on Linux. This is necessary for the cases when a sandbox prevents ASan from reading the mappings<br>
from /proc/self/maps.<br>
The mappings are currently being cached on each access to /proc/self/maps. In the future we'll need to add an API that allows the client to notify ASan about the sandbox.<br>
<br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=169076&r1=169075&r2=169076&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=169076&r1=169075&r2=169076&view=diff</a><br>


==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Fri Nov 30 20:39:45 2012<br>
@@ -16,6 +16,7 @@<br>
 #include "sanitizer_common.h"<br>
 #include "sanitizer_internal_defs.h"<br>
 #include "sanitizer_libc.h"<br>
+#include "sanitizer_mutex.h"<br>
 #include "sanitizer_placement_new.h"<br>
 #include "sanitizer_procmaps.h"<br>
<br>
@@ -217,13 +218,23 @@<br>
 }<br>
<br>
 // ----------------- sanitizer_procmaps.h<br>
+char *MemoryMappingLayout::cached_proc_self_maps_buff_ = NULL;<br>
+uptr MemoryMappingLayout::cached_proc_self_maps_buff_mmaped_size_ = 0;<br>
+uptr MemoryMappingLayout::cached_proc_self_maps_buff_len_ = 0;<br>
+StaticSpinMutex MemoryMappingLayout::cache_lock_;<br>
+<br>
 MemoryMappingLayout::MemoryMappingLayout() {<br>
   proc_self_maps_buff_len_ =<br>
       ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_,<br>
                        &proc_self_maps_buff_mmaped_size_, 1 << 26);<br>
-  CHECK_GT(proc_self_maps_buff_len_, 0);<br>
+  if (proc_self_maps_buff_mmaped_size_ == 0) {<br>
+    LoadFromCache();<br>
+    CHECK_GT(proc_self_maps_buff_len_, 0);<br>
+  }<br>
   // internal_write(2, proc_self_maps_buff_, proc_self_maps_buff_len_);<br>
   Reset();<br>
+  // FIXME: in the future we may want to cache the mappings on demand only.<br>
+  CacheMemoryMappings();<br>
 }<br>
<br>
 MemoryMappingLayout::~MemoryMappingLayout() {<br>
@@ -234,6 +245,39 @@<br>
   current_ = proc_self_maps_buff_;<br>
 }<br>
<br>
+// static<br>
+void MemoryMappingLayout::CacheMemoryMappings() {<br>
+  SpinMutexLock l(&cache_lock_);<br>
+  // Don't invalidate the cache if the mappings are unavailable.<br>
+  char *old_proc_self_maps_buff_ = cached_proc_self_maps_buff_;<br>
+  uptr old_proc_self_maps_buff_mmaped_size_ =<br>
+      cached_proc_self_maps_buff_mmaped_size_;<br>
+  uptr old_proc_self_maps_buff_len_ = cached_proc_self_maps_buff_len_;<br>
+  cached_proc_self_maps_buff_len_ =<br>
+      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_buff_,<br>
+                       &cached_proc_self_maps_buff_mmaped_size_, 1 << 26);<br>
+  if (cached_proc_self_maps_buff_mmaped_size_ == 0) {<br>
+    cached_proc_self_maps_buff_ = old_proc_self_maps_buff_;<br>
+    cached_proc_self_maps_buff_mmaped_size_ =<br>
+        old_proc_self_maps_buff_mmaped_size_;<br>
+    cached_proc_self_maps_buff_len_ = old_proc_self_maps_buff_len_;<br>
+  } else {<br>
+    if (old_proc_self_maps_buff_mmaped_size_) {<br>
+      UnmapOrDie(old_proc_self_maps_buff_,<br>
+                 old_proc_self_maps_buff_mmaped_size_);<br></blockquote><div><br></div></div></div><div>OMG. I really think we need to wrap buff_, mmaped_size_ and buff_len_ in struct.</div></div></div></blockquote><div>
+1 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-family:arial,helvetica,sans-serif;font-size:10pt"><div class="gmail_quote"><div><div class="h5">
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+    }<br>
+  }<br>
+}<br>
+<br>
+void MemoryMappingLayout::LoadFromCache() {<br>
+  SpinMutexLock l(&cache_lock_);<br>
+  if (cached_proc_self_maps_buff_) {<br>
+    proc_self_maps_buff_ = cached_proc_self_maps_buff_;<br>
+    proc_self_maps_buff_len_ = cached_proc_self_maps_buff_len_;<br>
+    proc_self_maps_buff_mmaped_size_ = cached_proc_self_maps_buff_mmaped_size_;<br>
+  }<br>
+}<br>
+<br>
 // Parse a hex value in str and update str.<br>
 static uptr ParseHex(char **str) {<br>
   uptr x = 0;<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=169076&r1=169075&r2=169076&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=169076&r1=169075&r2=169076&view=diff</a><br>


==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Fri Nov 30 20:39:45 2012<br>
@@ -162,6 +162,15 @@<br>
   current_filetype_ = 0;<br>
 }<br>
<br>
+// static<br>
+void MemoryMappingLayout::CacheMemoryMappings() {<br>
+  // No-op on Mac for now.<br>
+}<br>
+<br>
+void MemoryMappingLayout::LoadFromCache() {<br>
+  // No-op on Mac for now.<br>
+}<br>
+<br>
 // Next and NextSegmentLoad were inspired by base/sysinfo.cc in<br>
 // Google Perftools, <a href="http://code.google.com/p/google-perftools" target="_blank">http://code.google.com/p/google-perftools</a>.<br>
<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=169076&r1=169075&r2=169076&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=169076&r1=169075&r2=169076&view=diff</a><br>


==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h Fri Nov 30 20:39:45 2012<br>
@@ -15,6 +15,7 @@<br>
 #define SANITIZER_PROCMAPS_H<br>
<br>
 #include "sanitizer_internal_defs.h"<br>
+#include "sanitizer_mutex.h"<br>
<br>
 namespace __sanitizer {<br>
<br>
@@ -39,9 +40,14 @@<br>
   // address 'addr'. Returns true on success.<br>
   bool GetObjectNameAndOffset(uptr addr, uptr *offset,<br>
                               char filename[], uptr filename_size);<br>
+  // In some cases, e.g. when running under a sandbox on Linux, ASan is unable<br>
+  // to obtain the memory mappings. It should fall back to pre-cached data<br>
+  // instead of aborting.<br>
+  static void CacheMemoryMappings();<br>
   ~MemoryMappingLayout();<br>
<br>
  private:<br>
+  void LoadFromCache();<br>
   // Default implementation of GetObjectNameAndOffset.<br>
   // Quite slow, because it iterates through the whole process map for each<br>
   // lookup.<br>
@@ -77,6 +83,12 @@<br>
   uptr proc_self_maps_buff_mmaped_size_;<br>
   uptr proc_self_maps_buff_len_;<br>
   char *current_;<br>
+<br>
+  // Static mappings cache.<br>
+  static char *cached_proc_self_maps_buff_;<br>
+  static uptr cached_proc_self_maps_buff_mmaped_size_;<br>
+  static uptr cached_proc_self_maps_buff_len_;<br>
+  static StaticSpinMutex cache_lock_;  // protects the cache contents.<br>
 # elif defined __APPLE__<br>
   template<u32 kLCSegment, typename SegmentCommand><br>
   bool NextSegmentLoad(uptr *start, uptr *end, uptr *offset,<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div><br>
</font></span></div>
<br>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br></blockquote></div><br></div>