diff --git a/compiler-rt/lib/asan/asan_fuchsia.cpp b/compiler-rt/lib/asan/asan_fuchsia.cpp index 6876be1dca535..a9e5dad91b973 100644 --- a/compiler-rt/lib/asan/asan_fuchsia.cpp +++ b/compiler-rt/lib/asan/asan_fuchsia.cpp @@ -32,11 +32,11 @@ void EarlySanitizerInit() {} namespace __asan { -// The system already set up the shadow memory for us. -// __sanitizer::GetMaxUserVirtualAddress has already been called by -// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp). -// Just do some additional sanity checks here. void InitializeShadowMemory() { + // Explicitly setup shadow here right beforer any of the ShadowBounds members + // are used. + InitShadowBounds(); + if (Verbosity()) PrintAddressSpaceLayout(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index 625f30ceca1c2..3c61b60802996 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -14,6 +14,7 @@ #include "sanitizer_fuchsia.h" #if SANITIZER_FUCHSIA +# include # include # include # include @@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); } sanitizer_shadow_bounds_t ShadowBounds; +// Any sanitizer that utilizes shadow should explicitly call whenever it's +// appropriate for that sanitizer to reference shadow bounds. For ASan, this is +// done in `InitializeShadowMemory` and for HWASan, this is done in +// `InitShadow`. void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); } +// TODO(leonardchan): It's not immediately clear from a user perspective if +// `GetMaxUserVirtualAddress` should be called exatly once on runtime startup +// or can be called multiple times. Currently it looks like most instances of +// `GetMaxUserVirtualAddress` are meant to be called once, but if someone +// decides to call this multiple times in the future, we should have a separate +// function that's ok to call multiple times. Ideally we would just invoke this +// syscall once. Also for Fuchsia, this syscall technically gets invoked twice +// since `__sanitizer_shadow_bounds` also invokes this syscall under the hood. uptr GetMaxUserVirtualAddress() { - InitShadowBounds(); - return ShadowBounds.memory_limit - 1; + zx_info_vmar_t info; + zx_status_t status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, + &info, sizeof(info), NULL, NULL); + CHECK_EQ(status, ZX_OK); + + // Find the top of the accessible address space. + uintptr_t top = info.base + info.len; + + // Round it up to a power-of-two size. There may be some pages at + // the top that can't actually be mapped, but for purposes of the + // the shadow, we'll pretend they could be. + int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top); + if (top != (uintptr_t)1 << bit) + top = (uintptr_t)1 << (bit + 1); + + return top - 1; } uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }