]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_premap_shadow.cc
Merge compiler-rt trunk r321017 to contrib/compiler-rt.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_premap_shadow.cc
1 //===-- asan_premap_shadow.cc ---------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Reserve shadow memory with an ifunc resolver.
13 //===----------------------------------------------------------------------===//
14
15 #include "asan_mapping.h"
16
17 #if ASAN_PREMAP_SHADOW
18
19 #include "asan_premap_shadow.h"
20 #include "sanitizer_common/sanitizer_posix.h"
21
22 namespace __asan {
23
24 // The code in this file needs to run in an unrelocated binary. It may not
25 // access any external symbol, including its own non-hidden globals.
26
27 // Conservative upper limit.
28 uptr PremapShadowSize() {
29   uptr granularity = GetMmapGranularity();
30   return RoundUpTo(GetMaxVirtualAddress() >> SHADOW_SCALE, granularity);
31 }
32
33 // Returns an address aligned to 8 pages, such that one page on the left and
34 // PremapShadowSize() bytes on the right of it are mapped r/o.
35 uptr PremapShadow() {
36   uptr granularity = GetMmapGranularity();
37   uptr alignment = granularity * 8;
38   uptr left_padding = granularity;
39   uptr shadow_size = PremapShadowSize();
40   uptr map_size = shadow_size + left_padding + alignment;
41
42   uptr map_start = (uptr)MmapNoAccess(map_size);
43   CHECK_NE(map_start, ~(uptr)0);
44
45   uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
46   uptr shadow_end = shadow_start + shadow_size;
47   internal_munmap(reinterpret_cast<void *>(map_start),
48                   shadow_start - left_padding - map_start);
49   internal_munmap(reinterpret_cast<void *>(shadow_end),
50                   map_start + map_size - shadow_end);
51   return shadow_start;
52 }
53
54 bool PremapShadowFailed() {
55   uptr shadow = reinterpret_cast<uptr>(&__asan_shadow);
56   uptr resolver = reinterpret_cast<uptr>(&__asan_premap_shadow);
57   // shadow == resolver is how Android KitKat and older handles ifunc.
58   // shadow == 0 just in case.
59   if (shadow == 0 || shadow == resolver)
60     return true;
61   return false;
62 }
63 } // namespace __asan
64
65 extern "C" {
66 decltype(__asan_shadow)* __asan_premap_shadow() {
67   // The resolver may be called multiple times. Map the shadow just once.
68   static uptr premapped_shadow = 0;
69   if (!premapped_shadow) premapped_shadow = __asan::PremapShadow();
70   return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow);
71 }
72
73 // __asan_shadow is a "function" that has the same address as the first byte of
74 // the shadow mapping.
75 INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void
76 __asan_shadow();
77 }
78
79 #endif // ASAN_PREMAP_SHADOW