|
14 | 14 | #include "sanitizer_fuchsia.h"
|
15 | 15 | #if SANITIZER_FUCHSIA
|
16 | 16 |
|
| 17 | +# include <limits.h> |
17 | 18 | # include <pthread.h>
|
18 | 19 | # include <stdlib.h>
|
19 | 20 | # include <unistd.h>
|
@@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
|
117 | 118 |
|
118 | 119 | sanitizer_shadow_bounds_t ShadowBounds;
|
119 | 120 |
|
| 121 | +// Any sanitizer that utilizes shadow should explicitly call whenever it's |
| 122 | +// appropriate for that sanitizer to reference shadow bounds. For ASan, this is |
| 123 | +// done in `InitializeShadowMemory` and for HWASan, this is done in |
| 124 | +// `InitShadow`. |
120 | 125 | void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }
|
121 | 126 |
|
| 127 | +// TODO(leonardchan): It's not immediately clear from a user perspective if |
| 128 | +// `GetMaxUserVirtualAddress` should be called exatly once on runtime startup |
| 129 | +// or can be called multiple times. Currently it looks like most instances of |
| 130 | +// `GetMaxUserVirtualAddress` are meant to be called once, but if someone |
| 131 | +// decides to call this multiple times in the future, we should have a separate |
| 132 | +// function that's ok to call multiple times. Ideally we would just invoke this |
| 133 | +// syscall once. Also for Fuchsia, this syscall technically gets invoked twice |
| 134 | +// since `__sanitizer_shadow_bounds` also invokes this syscall under the hood. |
122 | 135 | uptr GetMaxUserVirtualAddress() {
|
123 |
| - InitShadowBounds(); |
124 |
| - return ShadowBounds.memory_limit - 1; |
| 136 | + zx_info_vmar_t info; |
| 137 | + zx_status_t status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, |
| 138 | + &info, sizeof(info), NULL, NULL); |
| 139 | + CHECK_EQ(status, ZX_OK); |
| 140 | + |
| 141 | + // Find the top of the accessible address space. |
| 142 | + uintptr_t top = info.base + info.len; |
| 143 | + |
| 144 | + // Round it up to a power-of-two size. There may be some pages at |
| 145 | + // the top that can't actually be mapped, but for purposes of the |
| 146 | + // the shadow, we'll pretend they could be. |
| 147 | + int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top); |
| 148 | + if (top != (uintptr_t)1 << bit) |
| 149 | + top = (uintptr_t)1 << (bit + 1); |
| 150 | + |
| 151 | + return top - 1; |
125 | 152 | }
|
126 | 153 |
|
127 | 154 | uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
|
|
0 commit comments