ASan support for the Zone
authorjkummerow@chromium.org <jkummerow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Mar 2014 10:01:53 +0000 (10:01 +0000)
committerjkummerow@chromium.org <jkummerow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 26 Mar 2014 10:01:53 +0000 (10:01 +0000)
R=jarin@chromium.org, kcc@google.com

Review URL: https://codereview.chromium.org/208743004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20266 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

Makefile
build/standalone.gypi
src/zone-inl.h
src/zone.cc
src/zone.h

index f390028..cdf5d74 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -136,7 +136,16 @@ endif
 # deprecation_warnings=on
 ifeq ($(deprecationwarnings), on)
   GYPFLAGS += -Dv8_deprecation_warnings=1
-endif 
+endif
+# asan=/path/to/clang++
+ifneq ($(strip $(asan)),)
+  GYPFLAGS += -Dasan=1
+  export CXX="$(asan)"
+  export CXX_host="$(asan)"
+  export LINK="$(asan)"
+  export ASAN_SYMBOLIZER_PATH="$(dir $(asan))llvm-symbolizer"
+endif
+
 # arm specific flags.
 # arm_version=<number | "default">
 ifneq ($(strip $(arm_version)),)
index 395ec4c..116cf8d 100644 (file)
         'ldflags': [
           '-fsanitize=address',
         ],
-      }
+        'defines': [
+          'ADDRESS_SANITIZER',
+        ],
+      },
     }],
     ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
        or OS=="netbsd"', {
index f257382..9a5de34 100644 (file)
 
 #include "zone.h"
 
+#ifdef ADDRESS_SANITIZER
+  #include <sanitizer/asan_interface.h>
+#else
+  #define ASAN_UNPOISON_MEMORY_REGION(start, size) ((void) 0)
+#endif
+
 #include "counters.h"
 #include "isolate.h"
 #include "utils.h"
@@ -39,6 +45,9 @@ namespace v8 {
 namespace internal {
 
 
+static const int kASanRedzoneBytes = 24;  // Must be a multiple of 8.
+
+
 inline void* Zone::New(int size) {
   // Round up the requested size to fit the alignment.
   size = RoundUp(size, kAlignment);
@@ -54,12 +63,25 @@ inline void* Zone::New(int size) {
   // Check if the requested size is available without expanding.
   Address result = position_;
 
-  if (size > limit_ - position_) {
-     result = NewExpand(size);
+  int size_with_redzone =
+#ifdef ADDRESS_SANITIZER
+      size + kASanRedzoneBytes;
+#else
+      size;
+#endif
+
+  if (size_with_redzone > limit_ - position_) {
+     result = NewExpand(size_with_redzone);
   } else {
-     position_ += size;
+     position_ += size_with_redzone;
   }
 
+#ifdef ADDRESS_SANITIZER
+  Address redzone_position = result + size;
+  ASSERT(redzone_position + kASanRedzoneBytes == position_);
+  ASAN_POISON_MEMORY_REGION(redzone_position, kASanRedzoneBytes);
+#endif
+
   // Check that the result has the proper alignment and return it.
   ASSERT(IsAddressAligned(result, kAlignment, 0));
   allocation_size_ += size;
@@ -69,6 +91,7 @@ inline void* Zone::New(int size) {
 
 template <typename T>
 T* Zone::NewArray(int length) {
+  CHECK(std::numeric_limits<int>::max() / static_cast<int>(sizeof(T)) > length);
   return static_cast<T*>(New(length * sizeof(T)));
 }
 
index 417f895..4f91371 100644 (file)
@@ -104,6 +104,8 @@ void Zone::DeleteAll() {
     } else {
       int size = current->size();
 #ifdef DEBUG
+      // Un-poison first so the zapping doesn't trigger ASan complaints.
+      ASAN_UNPOISON_MEMORY_REGION(current, size);
       // Zap the entire current segment (including the header).
       memset(current, kZapDeadByte, size);
 #endif
@@ -120,6 +122,8 @@ void Zone::DeleteAll() {
     Address start = keep->start();
     position_ = RoundUp(start, kAlignment);
     limit_ = keep->end();
+    // Un-poison so we can re-use the segment later.
+    ASAN_UNPOISON_MEMORY_REGION(start, keep->capacity());
 #ifdef DEBUG
     // Zap the contents of the kept segment (but not the header).
     memset(start, kZapDeadByte, keep->capacity());
@@ -143,6 +147,8 @@ void Zone::DeleteKeptSegment() {
   if (segment_head_ != NULL) {
     int size = segment_head_->size();
 #ifdef DEBUG
+    // Un-poison first so the zapping doesn't trigger ASan complaints.
+    ASAN_UNPOISON_MEMORY_REGION(segment_head_, size);
     // Zap the entire kept segment (including the header).
     memset(segment_head_, kZapDeadByte, size);
 #endif
index bd7cc39..75224a6 100644 (file)
@@ -89,8 +89,13 @@ class Zone {
 
   // All pointers returned from New() have this alignment.  In addition, if the
   // object being allocated has a size that is divisible by 8 then its alignment
-  // will be 8.
+  // will be 8. ASan requires 8-byte alignment.
+#ifdef ADDRESS_SANITIZER
+  static const int kAlignment = 8;
+  STATIC_ASSERT(kPointerSize <= 8);
+#else
   static const int kAlignment = kPointerSize;
+#endif
 
   // Never allocate segments smaller than this size in bytes.
   static const int kMinimumSegmentSize = 8 * KB;