From dc8c0dd36ba2c119772ec7e614ca33ec6463214e Mon Sep 17 00:00:00 2001 From: Kostya Kortchinsky Date: Mon, 27 Nov 2017 19:53:53 +0000 Subject: [fuchsia] Update Fuchsia with a new mmap implementation. Summary: Now that the sanitizer_common interface for MmapNoAccess / MmapFixed have been refactored to allow a more OO-esque access pattern, update the Fuchsia mmap implementation to take advantage of this. Previously MmapNoAccess / MmapFixed relied on a global allocator_vmar, since the sanitizer_allocator only called MmapNoAccess once. Now, we create a new VMAR per ReservedAddressRange object. This allows the sanitizer allocator to work in tandem with the Scudo secondary allocator. This is part 4 of a 4 part changeset: * part 1 https://reviews.llvm.org/D38593 * part 2 https://reviews.llvm.org/D38592 * part 3 https://reviews.llvm.org/D38593 Reviewers: mcgrathr, cryptoad Reviewed By: cryptoad Subscribers: alekseyshl, mcgrathr, kubamracek, mehdi_amini Differential Revision: https://reviews.llvm.org/D38595 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@319083 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_common.h | 1 + lib/sanitizer_common/sanitizer_fuchsia.cc | 162 ++++++++++-------------- lib/sanitizer_common/sanitizer_posix_libcdep.cc | 1 + lib/sanitizer_common/sanitizer_win.cc | 1 + 4 files changed, 73 insertions(+), 92 deletions(-) (limited to 'lib') diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 2633a9816..ceec58cd5 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -142,6 +142,7 @@ class ReservedAddressRange { void* base_; uptr size_; const char* name_; + uptr os_handle_; }; typedef void (*fill_profile_f)(uptr start, uptr rss, bool file, diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cc b/lib/sanitizer_common/sanitizer_fuchsia.cc index 23df9aad5..511d55e1d 100644 --- a/lib/sanitizer_common/sanitizer_fuchsia.cc +++ b/lib/sanitizer_common/sanitizer_fuchsia.cc @@ -191,9 +191,7 @@ uptr GetMaxUserVirtualAddress() { return ShadowBounds.memory_limit - 1; } -uptr GetMaxVirtualAddress() { - return GetMaxUserVirtualAddress(); -} +uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); } static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type, bool raw_report, bool die_for_nomem) { @@ -240,108 +238,96 @@ void *MmapOrDieOnFatalError(uptr size, const char *mem_type) { return DoAnonymousMmapOrDie(size, mem_type, false, false); } -uptr ReservedAddressRange::Init(uptr init_size, const char* name, +uptr ReservedAddressRange::Init(uptr init_size, const char *name, uptr fixed_addr) { - base_ = MmapNoAccess(init_size); - size_ = init_size; - name_ = name; - return reinterpret_cast(base_); -} - -// Uses fixed_addr for now. -// Will use offset instead once we've implemented this function for real. -uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size) { - return reinterpret_cast(MmapFixedOrDieOnFatalError(fixed_addr, - map_size)); -} - -uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size) { - return reinterpret_cast(MmapFixedOrDie(fixed_addr, map_size)); -} - -void ReservedAddressRange::Unmap(uptr addr, uptr size) { - void* addr_as_void = reinterpret_cast(addr); - uptr base_as_uptr = reinterpret_cast(base_); - // Only unmap at the beginning or end of the range. - CHECK((addr_as_void == base_) || (addr + size == base_as_uptr + size_)); - CHECK_LE(size, size_); - UnmapOrDie(reinterpret_cast(addr), size); - if (addr_as_void == base_) { - base_ = reinterpret_cast(addr + size); - } - size_ = size_ - size; -} - -// MmapNoAccess and MmapFixedOrDie are used only by sanitizer_allocator. -// Instead of doing exactly what they say, we make MmapNoAccess actually -// just allocate a VMAR to reserve the address space. Then MmapFixedOrDie -// uses that VMAR instead of the root. - -zx_handle_t allocator_vmar = ZX_HANDLE_INVALID; -uintptr_t allocator_vmar_base; -size_t allocator_vmar_size; - -void *MmapNoAccess(uptr size) { - size = RoundUpTo(size, PAGE_SIZE); - CHECK_EQ(allocator_vmar, ZX_HANDLE_INVALID); + init_size = RoundUpTo(init_size, PAGE_SIZE); + DCHECK_EQ(os_handle_, ZX_HANDLE_INVALID); uintptr_t base; + zx_handle_t vmar; zx_status_t status = - _zx_vmar_allocate(_zx_vmar_root_self(), 0, size, + _zx_vmar_allocate(_zx_vmar_root_self(), 0, init_size, ZX_VM_FLAG_CAN_MAP_READ | ZX_VM_FLAG_CAN_MAP_WRITE | ZX_VM_FLAG_CAN_MAP_SPECIFIC, - &allocator_vmar, &base); + &vmar, &base); if (status != ZX_OK) - ReportMmapFailureAndDie(size, "sanitizer allocator address space", - "zx_vmar_allocate", status); + ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status); + base_ = reinterpret_cast(base); + size_ = init_size; + name_ = name; + os_handle_ = vmar; - allocator_vmar_base = base; - allocator_vmar_size = size; - return reinterpret_cast(base); + return reinterpret_cast(base_); } -constexpr const char kAllocatorVmoName[] = "sanitizer_allocator"; - -static void *DoMmapFixedOrDie(uptr fixed_addr, uptr size, bool die_for_nomem) { - size = RoundUpTo(size, PAGE_SIZE); - +static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size, + void *base, const char *name, bool die_for_nomem) { + uptr offset = fixed_addr - reinterpret_cast(base); + map_size = RoundUpTo(map_size, PAGE_SIZE); zx_handle_t vmo; - zx_status_t status = _zx_vmo_create(size, 0, &vmo); + zx_status_t status = _zx_vmo_create(map_size, 0, &vmo); if (status != ZX_OK) { if (status != ZX_ERR_NO_MEMORY || die_for_nomem) - ReportMmapFailureAndDie(size, kAllocatorVmoName, "zx_vmo_create", status); - return nullptr; + ReportMmapFailureAndDie(map_size, name, "zx_vmo_create", status); + return 0; } - _zx_object_set_property(vmo, ZX_PROP_NAME, kAllocatorVmoName, - sizeof(kAllocatorVmoName) - 1); - - DCHECK_GE(fixed_addr, allocator_vmar_base); - uintptr_t offset = fixed_addr - allocator_vmar_base; - DCHECK_LE(size, allocator_vmar_size); - DCHECK_GE(allocator_vmar_size - offset, size); - + _zx_object_set_property(vmo, ZX_PROP_NAME, name, sizeof(name) - 1); + DCHECK_GE(base + size_, map_size + offset); uintptr_t addr; + status = _zx_vmar_map( - allocator_vmar, offset, vmo, 0, size, + vmar, offset, vmo, 0, map_size, ZX_VM_FLAG_PERM_READ | ZX_VM_FLAG_PERM_WRITE | ZX_VM_FLAG_SPECIFIC, &addr); _zx_handle_close(vmo); if (status != ZX_OK) { - if (status != ZX_ERR_NO_MEMORY || die_for_nomem) - ReportMmapFailureAndDie(size, kAllocatorVmoName, "zx_vmar_map", status); - return nullptr; + if (status != ZX_ERR_NO_MEMORY || die_for_nomem) { + ReportMmapFailureAndDie(map_size, name, "zx_vmar_map", status); + } + return 0; } + IncreaseTotalMmap(map_size); + return addr; +} - IncreaseTotalMmap(size); +uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size) { + return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, + name_, false); +} - return reinterpret_cast(addr); +uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size) { + return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_, + name_, true); } -void *MmapFixedOrDie(uptr fixed_addr, uptr size) { - return DoMmapFixedOrDie(fixed_addr, size, true); +void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) { + if (!addr || !size) return; + size = RoundUpTo(size, PAGE_SIZE); + + zx_status_t status = + _zx_vmar_unmap(target_vmar, reinterpret_cast(addr), size); + if (status != ZX_OK) { + Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", + SanitizerToolName, size, size, addr); + CHECK("unable to unmap" && 0); + } + + DecreaseTotalMmap(size); } -void *MmapFixedOrDieOnFatalError(uptr fixed_addr, uptr size) { - return DoMmapFixedOrDie(fixed_addr, size, false); +void ReservedAddressRange::Unmap(uptr fixed_addr, uptr size) { + uptr offset = fixed_addr - reinterpret_cast(base_); + uptr addr = reinterpret_cast(base_) + offset; + void *addr_as_void = reinterpret_cast(addr); + uptr base_as_uptr = reinterpret_cast(base_); + // Only unmap at the beginning or end of the range. + CHECK((addr_as_void == base_) || (addr + size == base_as_uptr + size_)); + CHECK_LE(size, size_); + UnmapOrDieVmar(reinterpret_cast(addr), size, + static_cast(os_handle_)); + if (addr_as_void == base_) { + base_ = reinterpret_cast(addr + size); + } + size_ = size_ - size; } // This should never be called. @@ -413,18 +399,7 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment, } void UnmapOrDie(void *addr, uptr size) { - if (!addr || !size) return; - size = RoundUpTo(size, PAGE_SIZE); - - zx_status_t status = _zx_vmar_unmap(_zx_vmar_root_self(), - reinterpret_cast(addr), size); - if (status != ZX_OK) { - Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", - SanitizerToolName, size, size, addr); - CHECK("unable to unmap" && 0); - } - - DecreaseTotalMmap(size); + UnmapOrDieVmar(addr, size, _zx_vmar_root_self()); } // This is used on the shadow mapping, which cannot be changed. @@ -432,7 +407,8 @@ void UnmapOrDie(void *addr, uptr size) { void ReleaseMemoryPagesToOS(uptr beg, uptr end) {} void DumpProcessMap() { - UNIMPLEMENTED(); // TODO(mcgrathr): write it + // TODO(mcgrathr): write it + return; } bool IsAccessibleMemoryRange(uptr beg, uptr size) { @@ -532,6 +508,8 @@ u32 GetNumberOfCPUs() { return zx_system_get_num_cpus(); } +uptr GetRSS() { UNIMPLEMENTED(); } + } // namespace __sanitizer using namespace __sanitizer; // NOLINT diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 20a5f42e4..710fdf3d6 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -350,6 +350,7 @@ uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) { } size_ = size; name_ = name; + (void)os_handle_; // unsupported return reinterpret_cast(base_); } diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index fab2babea..4f82025ed 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -286,6 +286,7 @@ uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) { } size_ = size; name_ = name; + (void)os_handle_; // unsupported return reinterpret_cast(base_); } -- cgit v1.2.3