Index: lib/asan/asan_allocator.cc =================================================================== --- lib/asan/asan_allocator.cc +++ lib/asan/asan_allocator.cc @@ -20,15 +20,16 @@ #include "asan_report.h" #include "asan_stack.h" #include "asan_thread.h" +#include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_allocator_checks.h" #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_errno.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_list.h" -#include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_quarantine.h" -#include "lsan/lsan_common.h" +#include "sanitizer_common/sanitizer_remote_address_space_view.h" +#include "sanitizer_common/sanitizer_stackdepot.h" namespace __asan { @@ -125,6 +126,8 @@ bool AddrIsInside(uptr addr, bool locked_version = false) { return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version)); } + // Allow class to access private methods for out-of-process use case. + friend class __lsan::LsanMetadataRemoteView; private: // Common code for in-process and out-of-process chunk examination. @@ -1120,6 +1123,52 @@ return m->alloc_context_id; } +LsanMetadataRemoteView::LsanMetadataRemoteView(uptr block_begin, uptr allocator) + : LsanMetadata(0) { + CHECK(block_begin); + CHECK(allocator); + this->block_begin_target_ = block_begin; + this->allocator_ = allocator; + + // We expect the `block_begin` pointer to actually point to the beginning + // of an allocator block. +#if SANITIZER_DEBUG + using RemoteAllocatorTy = __asan::AsanAllocatorASVT; + DCHECK_EQ(reinterpret_cast(allocator)->GetBlockBegin( + reinterpret_cast(block_begin_target_)), + block_begin_target_); +#endif + + // Determine the address of the AsanChunk in the target process. + auto chunk_addr = __asan::GetAsanChunkInternal( + block_begin_target_, allocator_); + metadata_target_ = reinterpret_cast(chunk_addr); + + // Copy the AsanChunk into the local process. + const __asan::AsanChunk *asan_chunk = + RemoteAddressSpaceView::Load(chunk_addr); + metadata_ = + reinterpret_cast(const_cast<__asan::AsanChunk *>(asan_chunk)); +} + +void LsanMetadataRemoteView::set_tag(ChunkTag value) { + CHECK(0 && "Unsupported operation"); +} + +uptr LsanMetadataRemoteView::requested_size() const { + auto asan_chunk = reinterpret_cast<__asan::AsanChunk *>(metadata_); + // NOTE: We provide `known_alloc_beg` as an optimization. + return asan_chunk->UsedSizeInternal( + /*chunk_storage_addr=*/metadata_target_, + /*locked_version=*/false, /*allocator=*/allocator_, + /*known_alloc_beg=*/reinterpret_cast(block_begin_target_)); +} + +uptr LsanMetadataRemoteView::user_begin() const { + auto asan_chunk = reinterpret_cast<__asan::AsanChunk *>(metadata_); + return asan_chunk->BegInternal(/*chunk_storage_addr=*/metadata_target_); +} + void ForEachChunk(ForEachChunkCallback callback, void *arg) { __asan::get_allocator().ForEachChunk(callback, arg); } Index: lib/lsan/lsan_common.h =================================================================== --- lib/lsan/lsan_common.h +++ lib/lsan/lsan_common.h @@ -244,10 +244,35 @@ void set_tag(ChunkTag value); uptr requested_size() const; u32 stack_trace_id() const; - private: + + protected: void *metadata_; }; +class LsanMetadataRemoteView : public LsanMetadata { + // For efficiency reasons we require a pointer to the beginning of + // the underlying allocator block (i.e. what `ForEachChunk` gives to its call + // back). This is different from `LsanMetadata` which expects a pointer + // to the beginning of user data. + // + // `block_begin` - Pointer to the beginning of an allocator block in + // target process (as returned by GetBlockBegin() and reported + // by ForEachChunk()). + // + // `allocator` - Pointer to allocator. This should be in the local + // address space. + public: + LsanMetadataRemoteView(uptr block_begin, uptr allocator); + void set_tag(ChunkTag value); + uptr requested_size() const; + uptr user_begin() const; + + private: + uptr metadata_target_; + uptr block_begin_target_; + uptr allocator_; +}; + } // namespace __lsan extern "C" {