From b2c744f7f7dad3e6d7bd9c485c323b8bd0cddb5d Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 10 Mar 2016 20:47:26 +0000 Subject: [Windows] Fix UnmapOrDie and MmapAlignedOrDie Now ASan can return virtual memory to the underlying OS. Portable sanitizer runtime code needs to be aware that UnmapOrDie cannot unmap part of previous mapping. In particular, this required changing how we implement MmapAlignedOrDie on Windows, which is what Allocator32 uses. The new code first attempts to allocate memory of the given size, and if it is appropriately aligned, returns early. If not, it frees the memory and attempts to reserve size + alignment bytes. In this region there must be an aligned address. We then free the oversized mapping and request a new mapping at the aligned address immediately after. However, a thread could allocate that virtual address in between our free and allocation, so we have to retry if that allocation fails. The existing thread creation stress test managed to trigger this condition, so the code isn't totally untested. Reviewers: samsonov Differential Revision: http://reviews.llvm.org/D17431 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@263160 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_posix.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib/sanitizer_common/sanitizer_posix.cc') diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index a383b2158..5bcc86b3b 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -139,6 +139,26 @@ void UnmapOrDie(void *addr, uptr size) { DecreaseTotalMmap(size); } +// We want to map a chunk of address space aligned to 'alignment'. +// We do it by maping a bit more and then unmaping redundant pieces. +// We probably can do it with fewer syscalls in some OS-dependent way. +void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) { + CHECK(IsPowerOfTwo(size)); + CHECK(IsPowerOfTwo(alignment)); + uptr map_size = size + alignment; + uptr map_res = (uptr)MmapOrDie(map_size, mem_type); + uptr map_end = map_res + map_size; + uptr res = map_res; + if (res & (alignment - 1)) // Not aligned. + res = (map_res + alignment) & ~(alignment - 1); + uptr end = res + size; + if (res != map_res) + UnmapOrDie((void*)map_res, res - map_res); + if (end != map_end) + UnmapOrDie((void*)end, map_end - end); + return (void*)res; +} + void *MmapNoReserveOrDie(uptr size, const char *mem_type) { uptr PageSize = GetPageSizeCached(); uptr p = internal_mmap(nullptr, -- cgit v1.2.3