diff options
| author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2017-11-10 22:27:48 +0000 |
|---|---|---|
| committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2017-11-10 22:27:48 +0000 |
| commit | 989299c42b00d2cfedd1c65f663b51ee45d84f69 (patch) | |
| tree | a62ab30ce0c82302d55b360b375f9eee99928ec8 /compiler-rt/lib/asan/asan_premap_shadow.cc | |
| parent | ba664c1d047a7ec1ac86adaf178bf829cdfd5961 (diff) | |
| download | bcm5719-llvm-989299c42b00d2cfedd1c65f663b51ee45d84f69.tar.gz bcm5719-llvm-989299c42b00d2cfedd1c65f663b51ee45d84f69.zip | |
[asan] Use dynamic shadow on 32-bit Android.
Summary:
The following kernel change has moved ET_DYN base to 0x4000000 on arm32:
https://marc.info/?l=linux-kernel&m=149825162606848&w=2
Switch to dynamic shadow base to avoid such conflicts in the future.
Reserve shadow memory in an ifunc resolver, but don't use it in the instrumentation
until PR35221 is fixed. This will eventually let use save one load per function.
Reviewers: kcc
Subscribers: aemerson, srhines, kubamracek, kristof.beyls, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D39393
llvm-svn: 317943
Diffstat (limited to 'compiler-rt/lib/asan/asan_premap_shadow.cc')
| -rw-r--r-- | compiler-rt/lib/asan/asan_premap_shadow.cc | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_premap_shadow.cc b/compiler-rt/lib/asan/asan_premap_shadow.cc new file mode 100644 index 00000000000..0e66eeef126 --- /dev/null +++ b/compiler-rt/lib/asan/asan_premap_shadow.cc @@ -0,0 +1,69 @@ +//===-- asan_premap_shadow.cc ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// Reserve shadow memory with an ifunc resolver. +//===----------------------------------------------------------------------===// + +#include "asan_mapping.h" + +#if ASAN_PREMAP_SHADOW + +#include "asan_premap_shadow.h" +#include "sanitizer_common/sanitizer_posix.h" + +namespace __asan { + +// The code in this file needs to run in an unrelocated binary. It may not +// access any external symbol, including its own non-hidden globals. + +// Conservative upper limit. +uptr PremapShadowSize() { + return GetMaxVirtualAddress() >> SHADOW_SCALE; +} + +// Returns an address aligned to 8 pages, such that one page on the left and +// PremapShadowSize() bytes on the right of it are mapped r/o. +uptr PremapShadow() { + uptr granularity = GetMmapGranularity(); + uptr alignment = granularity * 8; + uptr left_padding = granularity; + uptr shadow_size = PremapShadowSize(); + uptr map_size = shadow_size + left_padding + alignment; + + uptr map_start = (uptr)MmapNoAccess(map_size); + CHECK_NE(map_start, ~(uptr)0); + + uptr shadow_start = RoundUpTo(map_start + left_padding, alignment); + uptr shadow_end = shadow_start + shadow_size; + internal_munmap(reinterpret_cast<void *>(map_start), + shadow_start - left_padding - map_start); + internal_munmap(reinterpret_cast<void *>(shadow_end), + map_start + map_size - shadow_end); + return shadow_start; +} + +} // namespace __asan + +extern "C" { +decltype(__asan_shadow)* __asan_premap_shadow() { + // The resolver may be called multiple times. Map the shadow just once. + static uptr premapped_shadow = 0; + if (!premapped_shadow) premapped_shadow = __asan::PremapShadow(); + return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow); +} + +// __asan_shadow is a "function" that has the same address as the first byte of +// the shadow mapping. +INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void +__asan_shadow(); +} + +#endif // ASAN_PREMAP_SHADOW |

