Fix ifunc detection in target-supports.exp file.
[official-gcc.git] / libsanitizer / asan / asan_shadow_setup.cc
blob9629b36798ff565e30412e5a82314892da0c4a58
1 //===-- asan_shadow_setup.cc ----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of AddressSanitizer, an address sanity checker.
9 //
10 // Set up the shadow memory.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_platform.h"
15 // asan_fuchsia.cc has its own InitializeShadowMemory implementation.
16 #if !SANITIZER_FUCHSIA
18 #include "asan_internal.h"
19 #include "asan_mapping.h"
21 namespace __asan {
23 // ---------------------- mmap -------------------- {{{1
24 // Reserve memory range [beg, end].
25 // We need to use inclusive range because end+1 may not be representable.
26 void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
27 CHECK_EQ((beg % GetMmapGranularity()), 0);
28 CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
29 uptr size = end - beg + 1;
30 DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
31 void *res = MmapFixedNoReserve(beg, size, name);
32 if (res != (void *)beg) {
33 Report(
34 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
35 "Perhaps you're using ulimit -v\n",
36 size);
37 Abort();
39 if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size);
40 if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
43 static void ProtectGap(uptr addr, uptr size) {
44 if (!flags()->protect_shadow_gap) {
45 // The shadow gap is unprotected, so there is a chance that someone
46 // is actually using this memory. Which means it needs a shadow...
47 uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
48 uptr GapShadowEnd =
49 RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
50 if (Verbosity())
51 Printf(
52 "protect_shadow_gap=0:"
53 " not protecting shadow gap, allocating gap's shadow\n"
54 "|| `[%p, %p]` || ShadowGap's shadow ||\n",
55 GapShadowBeg, GapShadowEnd);
56 ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
57 "unprotected gap shadow");
58 return;
60 void *res = MmapFixedNoAccess(addr, size, "shadow gap");
61 if (addr == (uptr)res) return;
62 // A few pages at the start of the address space can not be protected.
63 // But we really want to protect as much as possible, to prevent this memory
64 // being returned as a result of a non-FIXED mmap().
65 if (addr == kZeroBaseShadowStart) {
66 uptr step = GetMmapGranularity();
67 while (size > step && addr < kZeroBaseMaxShadowStart) {
68 addr += step;
69 size -= step;
70 void *res = MmapFixedNoAccess(addr, size, "shadow gap");
71 if (addr == (uptr)res) return;
75 Report(
76 "ERROR: Failed to protect the shadow gap. "
77 "ASan cannot proceed correctly. ABORTING.\n");
78 DumpProcessMap();
79 Die();
82 static void MaybeReportLinuxPIEBug() {
83 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__aarch64__))
84 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
85 Report(
86 "See https://github.com/google/sanitizers/issues/856 for possible "
87 "workarounds.\n");
88 #endif
91 void InitializeShadowMemory() {
92 // Set the shadow memory address to uninitialized.
93 __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
95 uptr shadow_start = kLowShadowBeg;
96 // Detect if a dynamic shadow address must used and find a available location
97 // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
98 // expands to |__asan_shadow_memory_dynamic_address| which is
99 // |kDefaultShadowSentinel|.
100 if (shadow_start == kDefaultShadowSentinel) {
101 __asan_shadow_memory_dynamic_address = 0;
102 CHECK_EQ(0, kLowShadowBeg);
103 shadow_start = FindDynamicShadowStart();
105 // Update the shadow memory address (potentially) used by instrumentation.
106 __asan_shadow_memory_dynamic_address = shadow_start;
108 if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
109 bool full_shadow_is_available =
110 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
112 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
113 !ASAN_FIXED_MAPPING
114 if (!full_shadow_is_available) {
115 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
116 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
118 #endif
120 if (Verbosity()) PrintAddressSpaceLayout();
122 if (full_shadow_is_available) {
123 // mmap the low shadow plus at least one page at the left.
124 if (kLowShadowBeg)
125 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
126 // mmap the high shadow.
127 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
128 // protect the gap.
129 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
130 CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
131 } else if (kMidMemBeg &&
132 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
133 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
134 CHECK(kLowShadowBeg != kLowShadowEnd);
135 // mmap the low shadow plus at least one page at the left.
136 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
137 // mmap the mid shadow.
138 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
139 // mmap the high shadow.
140 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
141 // protect the gaps.
142 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
143 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
144 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
145 } else {
146 Report(
147 "Shadow memory range interleaves with an existing memory mapping. "
148 "ASan cannot proceed correctly. ABORTING.\n");
149 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
150 shadow_start, kHighShadowEnd);
151 MaybeReportLinuxPIEBug();
152 DumpProcessMap();
153 Die();
157 } // namespace __asan
159 #endif // !SANITIZER_FUCHSIA