Start adding the supporting code to perform out-of-process allocator

enumeration.

Summary:

This patch introduces the local portion (`LocalAddressSpaceView`) of the
`AddressSpaceView` abstraction and modifies the secondary allocator
so that the `ForEachChunk()` method (and its callees) would work in the
out-of-process case when `AddressSpaceView` is `RemoteAddressSpaceView`.

The `AddressSpaceView` abstraction simply maps pointers from a target
process to a pointer in the local process (via its `Load()` method). For
the local (in-process) case this is a no-op. For the remote
(out-of-process) case this is not a no-op. The implementation of the
out-of-process `RemoteAddressSpaceView` is not included in this patch
and will be introduced later.

This patch is considerably simpler than the `ObjectView` abstraction
used in previous patches but lacks the type safety and stricter memory
management of the `ObjectView` abstraction.

This patch does not introduce any tests because with
`LocalAddressSpaceView` it should be a non functional change and unit
tests already cover the secondary allocator.  When
`RemoteAddressSpaceView` is landed tests will be added to ensure that it
functions as expected.

rdar://problem/45284065

Reviewers: kcc, kubamracek, dvyukov, vitalybuka, cryptoad,
george.karpenkov, morehouse

Subscribers: #sanitizers, llvm-commits

Differential Revision: https://reviews.llvm.org/D53975

llvm-svn: 346956
This commit is contained in:
Dan Liew 2018-11-15 14:20:28 +00:00
parent fd4d45514f
commit ee6eb9b25a
4 changed files with 66 additions and 9 deletions

View File

@ -144,6 +144,7 @@ set(SANITIZER_IMPL_HEADERS
sanitizer_libignore.h
sanitizer_linux.h
sanitizer_list.h
sanitizer_local_address_space_view.h
sanitizer_mac.h
sanitizer_malloc_mac.inc
sanitizer_mutex.h

View File

@ -14,12 +14,13 @@
#ifndef SANITIZER_ALLOCATOR_H
#define SANITIZER_ALLOCATOR_H
#include "sanitizer_internal_defs.h"
#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_lfstack.h"
#include "sanitizer_libc.h"
#include "sanitizer_list.h"
#include "sanitizer_local_address_space_view.h"
#include "sanitizer_mutex.h"
#include "sanitizer_lfstack.h"
#include "sanitizer_procmaps.h"
namespace __sanitizer {

View File

@ -68,7 +68,8 @@ typedef LargeMmapAllocatorPtrArrayDynamic DefaultLargeMmapAllocatorPtrArray;
// The main purpose of this allocator is to cover large and rare allocation
// sizes not covered by more efficient allocators (e.g. SizeClassAllocator64).
template <class MapUnmapCallback = NoOpMapUnmapCallback,
class PtrArrayT = DefaultLargeMmapAllocatorPtrArray>
class PtrArrayT = DefaultLargeMmapAllocatorPtrArray,
class AddressSpaceView = LocalAddressSpaceView>
class LargeMmapAllocator {
public:
void InitLinkerInitialized() {
@ -202,9 +203,10 @@ class LargeMmapAllocator {
void EnsureSortedChunks() {
if (chunks_sorted_) return;
Sort(reinterpret_cast<uptr *>(chunks_), n_chunks_);
Header **chunks = AddressSpaceView::Load(chunks_, n_chunks_);
Sort(reinterpret_cast<uptr *>(chunks), n_chunks_);
for (uptr i = 0; i < n_chunks_; i++)
chunks_[i]->chunk_idx = i;
AddressSpaceView::Load(chunks[i])->chunk_idx = i;
chunks_sorted_ = true;
}
@ -272,12 +274,13 @@ class LargeMmapAllocator {
// The allocator must be locked when calling this function.
void ForEachChunk(ForEachChunkCallback callback, void *arg) {
EnsureSortedChunks(); // Avoid doing the sort while iterating.
Header **chunks = AddressSpaceView::Load(chunks_, n_chunks_);
for (uptr i = 0; i < n_chunks_; i++) {
auto t = chunks_[i];
Header *t = chunks[i];
callback(reinterpret_cast<uptr>(GetUser(t)), arg);
// Consistency check: verify that the array did not change.
CHECK_EQ(chunks_[i], t);
CHECK_EQ(chunks_[i]->chunk_idx, i);
CHECK_EQ(chunks[i], t);
CHECK_EQ(AddressSpaceView::Load(chunks[i])->chunk_idx, i);
}
}
@ -316,4 +319,3 @@ class LargeMmapAllocator {
} stats;
StaticSpinMutex mutex_;
};

View File

@ -0,0 +1,53 @@
//===-- sanitizer_local_address_space_view.h --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// `LocalAddressSpaceView` provides the local (i.e. target and current address
// space are the same) implementation of the `AddressSpaveView` interface which
// provides a simple interface to load memory from another process (i.e.
// out-of-process)
//
// The `AddressSpaveView` interface requires that the type can be used as a
// template parameter to objects that wish to be able to operate in an
// out-of-process manner. In normal usage, objects are in-process and are thus
// instantiated with the `LocalAddressSpaceView` type. This type is used to
// load any pointers in instance methods. This implementation is effectively
// a no-op. When an object is to be used in an out-of-process manner it is
// instansiated with the `RemoteAddressSpaceView` type.
//
// By making `AddressSpaceView` a template parameter of an object, it can
// change its implementation at compile time which has no run time overhead.
// This also allows unifying in-process and out-of-process code which avoids
// code duplication.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
#define SANITIZER_LOCAL_ADDRES_SPACE_VIEW_H
namespace __sanitizer {
struct LocalAddressSpaceView {
// Load memory `sizeof(T) * num_elements` bytes of memory
// from the target process (always local for this implementation)
// starting at address `target_address`. The local copy of
// this memory is returned as a pointer. It is guaranteed that
//
// * That the function will always return the same value
// for a given set of arguments.
// * That the memory returned is writable and that writes will persist.
//
// The lifetime of loaded memory is implementation defined.
template <typename T>
static T *Load(T *target_address, uptr num_elements = 1) {
// The target address space is the local address space so
// nothing needs to be copied. Just return the pointer.
return target_address;
}
};
} // namespace __sanitizer
#endif