[compiler-rt][Fuchsia] Change GetMaxUserVirtualAddress to invoke syscall (#153309)
LSan was recently refactored to call GetMaxUserVirtualAddress for diagnostic purposes. This leads to failures for some of our downstream tests which only run with lsan. This occurs because GetMaxUserVirtualAddress depends on setting up shadow via a call to __sanitizer_shadow_bounds, but shadow bounds aren't set for standalone lsan because it doesn't use shadow. This updates the function to invoke the same syscall used by __sanitizer_shadow_bounds calls for getting the memory limit. Ideally this function would only be called once since we only need to get the bounds once. More context in https://fxbug.dev/437346226.
This commit is contained in:
parent
8cb6bfe05a
commit
3c8652e737
@ -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();
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "sanitizer_fuchsia.h"
|
||||
#if SANITIZER_FUCHSIA
|
||||
|
||||
# include <limits.h>
|
||||
# include <pthread.h>
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
@ -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(); }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user