[PATCH] D56968: Refactor `AsanChunk` methods into code that supports both in-process and out-of-process examination of `AsanChunk`s.

Dan Liew via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 19 15:51:24 PST 2019


delcypher created this revision.
delcypher added reviewers: kcc, vitalybuka, dvyukov, cryptoad, eugenis, george.karpenkov, yln, kubamracek.
Herald added a subscriber: Sanitizers.

This refactors the implementations of the `Beg()`, `UsedSize()` and
`AllocBeg()` methods. We do not modify `AddrIsInside()` because
future patches do not need use that method in an out-of-process context.

The common code is `private` and has the `Internal` suffix. Future
patches will use these new methods in an out-of-process context.

The `UsedSizeInternal(...)` method takes a new argument
(`known_alloc_beg`) which allows access to be optimized if the
result of `AllocBegInternal()` is already known. We will use this
in future patches.

We do not template `AsanChunk` type with `AddressSpaceView` like
we did for the allocators for several reasons.

- `AsanChunk` is different in that we need the both the pointer to the copy of the `AsanChunk` in the local process and its address in the remote process.
- Changing the `AsanChunk` type to take a template parameter risks changing its data layout (C++ gives no guarantees) which is undesirable.


Repository:
  rCRT Compiler Runtime

https://reviews.llvm.org/D56968

Files:
  lib/asan/asan_allocator.cc


Index: lib/asan/asan_allocator.cc
===================================================================
--- lib/asan/asan_allocator.cc
+++ lib/asan/asan_allocator.cc
@@ -111,24 +111,79 @@
 };
 
 struct AsanChunk: ChunkBase {
-  uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
+  uptr Beg() { return BegInternal(reinterpret_cast<uptr>(this)); }
   uptr UsedSize(bool locked_version = false) {
-    if (user_requested_size != SizeClassMap::kMaxSize)
-      return user_requested_size;
-    return *reinterpret_cast<uptr *>(
-               get_allocator().GetMetaData(AllocBeg(locked_version)));
+    return UsedSizeInternal<LocalAddressSpaceView>(
+        reinterpret_cast<uptr>(this), locked_version,
+        reinterpret_cast<uptr>(&get_allocator()), nullptr);
   }
   void *AllocBeg(bool locked_version = false) {
+    return AllocBegInternal<LocalAddressSpaceView>(
+        reinterpret_cast<uptr>(this), locked_version,
+        reinterpret_cast<uptr>(&get_allocator()));
+  }
+  bool AddrIsInside(uptr addr, bool locked_version = false) {
+    return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version));
+  }
+
+ private:
+  // Common code for in-process and out-of-process chunk examination.
+  //
+  // * For the in-process case `chunk_storage_addr` is the same as the `this`
+  //   pointer. For the out-of-process case it is a pointer to the
+  //   `AsanChunk` in the target process.
+  // * `allocator` is a pointer to the allocator in the local
+  //   address space, instantiated with the appropriate `AddressSpaceView`
+  //   template parameter. For the `out-of-process` case this means the client
+  //   is responsible for copying the allocator from the target process into
+  //   the client.
+
+  uptr BegInternal(uptr chunk_storage_addr) {
+    return chunk_storage_addr + kChunkHeaderSize;
+  }
+
+  template <typename AddressSpaceView>
+  void *AllocBegInternal(uptr chunk_storage_addr, bool locked_version,
+                         uptr allocator) {
     if (from_memalign) {
+      auto allocator_ptr =
+          reinterpret_cast<AsanAllocatorASVT<AddressSpaceView> *>(allocator);
       if (locked_version)
-        return get_allocator().GetBlockBeginFastLocked(
-            reinterpret_cast<void *>(this));
-      return get_allocator().GetBlockBegin(reinterpret_cast<void *>(this));
+        return allocator_ptr->GetBlockBeginFastLocked(
+            reinterpret_cast<void *>(chunk_storage_addr));
+      return allocator_ptr->GetBlockBegin(
+          reinterpret_cast<void *>(chunk_storage_addr));
     }
-    return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log));
+    return reinterpret_cast<void *>(BegInternal(chunk_storage_addr) -
+                                    RZLog2Size(rz_log));
   }
-  bool AddrIsInside(uptr addr, bool locked_version = false) {
-    return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version));
+
+  // `known_alloc_beg` - Address of the beginning of the underlying
+  // allocator block in the target process.
+  // If not set to zero then the following must be true `known_alloc_beg ==
+  // AllocBegInternal(chunk_storage_addr, lockec_version, allocator)`. If set to
+  // `0` then `AllocBegInternal()` will be called to determine the
+  // the address of the allocator block.
+  //
+  // This is an optimization to avoid calling `AllocBegInternal()` when
+  // the result of `AllocBegInternal(...)` is already know by the
+  // caller.
+  template <typename AddressSpaceView>
+  uptr UsedSizeInternal(uptr chunk_storage_addr, bool locked_version,
+                        uptr allocator, void *known_alloc_beg) {
+    if (user_requested_size != SizeClassMap::kMaxSize)
+      return user_requested_size;
+    if (!known_alloc_beg) {
+      known_alloc_beg = AllocBegInternal<AddressSpaceView>(
+          chunk_storage_addr, locked_version, allocator);
+    } else {
+      DCHECK_EQ(known_alloc_beg,
+                AllocBegInternal<AddressSpaceView>(chunk_storage_addr,
+                                                   locked_version, allocator));
+    }
+    return *AddressSpaceView::Load(reinterpret_cast<uptr *>(
+        reinterpret_cast<AsanAllocatorASVT<AddressSpaceView> *>(allocator)
+            ->GetMetaData(known_alloc_beg)));
   }
 };
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D56968.182688.patch
Type: text/x-patch
Size: 4272 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190119/e8c79e7e/attachment.bin>


More information about the llvm-commits mailing list