forked from OSchip/llvm-project
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:
parent
fd4d45514f
commit
ee6eb9b25a
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue