xref: /llvm-project/compiler-rt/lib/hwasan/hwasan.cpp (revision a0bb2e21c10bebcdb6bc6b8bc18f74dcf7c4b8b2)
1e3b6d110SNico Weber //===-- hwasan.cpp --------------------------------------------------------===//
2e3b6d110SNico Weber //
3e3b6d110SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e3b6d110SNico Weber // See https://llvm.org/LICENSE.txt for license information.
5e3b6d110SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e3b6d110SNico Weber //
7e3b6d110SNico Weber //===----------------------------------------------------------------------===//
8e3b6d110SNico Weber //
9e3b6d110SNico Weber // This file is a part of HWAddressSanitizer.
10e3b6d110SNico Weber //
11e3b6d110SNico Weber // HWAddressSanitizer runtime.
12e3b6d110SNico Weber //===----------------------------------------------------------------------===//
13e3b6d110SNico Weber 
14e3b6d110SNico Weber #include "hwasan.h"
15e26b25f8SMitch Phillips 
16e3b6d110SNico Weber #include "hwasan_checks.h"
17e3b6d110SNico Weber #include "hwasan_dynamic_shadow.h"
18e26b25f8SMitch Phillips #include "hwasan_globals.h"
198c60e0b6SMatt Morehouse #include "hwasan_mapping.h"
20e3b6d110SNico Weber #include "hwasan_poisoning.h"
21e3b6d110SNico Weber #include "hwasan_report.h"
22e3b6d110SNico Weber #include "hwasan_thread.h"
23e3b6d110SNico Weber #include "hwasan_thread_list.h"
24e3b6d110SNico Weber #include "sanitizer_common/sanitizer_atomic.h"
25e3b6d110SNico Weber #include "sanitizer_common/sanitizer_common.h"
26e3b6d110SNico Weber #include "sanitizer_common/sanitizer_flag_parser.h"
27e3b6d110SNico Weber #include "sanitizer_common/sanitizer_flags.h"
2854e96ac8SDmitry Vyukov #include "sanitizer_common/sanitizer_interface_internal.h"
29e3b6d110SNico Weber #include "sanitizer_common/sanitizer_libc.h"
30e3b6d110SNico Weber #include "sanitizer_common/sanitizer_procmaps.h"
31e3b6d110SNico Weber #include "sanitizer_common/sanitizer_stackdepot.h"
32e3b6d110SNico Weber #include "sanitizer_common/sanitizer_stacktrace.h"
33e3b6d110SNico Weber #include "sanitizer_common/sanitizer_symbolizer.h"
34e3b6d110SNico Weber #include "ubsan/ubsan_flags.h"
35e3b6d110SNico Weber #include "ubsan/ubsan_init.h"
36e3b6d110SNico Weber 
37e3b6d110SNico Weber // ACHTUNG! No system header includes in this file.
38e3b6d110SNico Weber 
39e3b6d110SNico Weber using namespace __sanitizer;
40e3b6d110SNico Weber 
41e3b6d110SNico Weber namespace __hwasan {
42e3b6d110SNico Weber 
43e3b6d110SNico Weber static Flags hwasan_flags;
44e3b6d110SNico Weber 
45e3b6d110SNico Weber Flags *flags() {
46e3b6d110SNico Weber   return &hwasan_flags;
47e3b6d110SNico Weber }
48e3b6d110SNico Weber 
49e3b6d110SNico Weber int hwasan_inited = 0;
50e3b6d110SNico Weber int hwasan_instrumentation_inited = 0;
51e3b6d110SNico Weber bool hwasan_init_is_running;
52e3b6d110SNico Weber 
53e3b6d110SNico Weber int hwasan_report_count = 0;
54e3b6d110SNico Weber 
55b270c3fbSLeonard Chan uptr kLowShadowStart;
56b270c3fbSLeonard Chan uptr kLowShadowEnd;
57b270c3fbSLeonard Chan uptr kHighShadowStart;
58b270c3fbSLeonard Chan uptr kHighShadowEnd;
59b270c3fbSLeonard Chan 
60e3b6d110SNico Weber void Flags::SetDefaults() {
61e3b6d110SNico Weber #define HWASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
62e3b6d110SNico Weber #include "hwasan_flags.inc"
63e3b6d110SNico Weber #undef HWASAN_FLAG
64e3b6d110SNico Weber }
65e3b6d110SNico Weber 
66e3b6d110SNico Weber static void RegisterHwasanFlags(FlagParser *parser, Flags *f) {
67e3b6d110SNico Weber #define HWASAN_FLAG(Type, Name, DefaultValue, Description) \
68e3b6d110SNico Weber   RegisterFlag(parser, #Name, Description, &f->Name);
69e3b6d110SNico Weber #include "hwasan_flags.inc"
70e3b6d110SNico Weber #undef HWASAN_FLAG
71e3b6d110SNico Weber }
72e3b6d110SNico Weber 
73e3b6d110SNico Weber static void InitializeFlags() {
74e3b6d110SNico Weber   SetCommonFlagsDefaults();
75e3b6d110SNico Weber   {
76e3b6d110SNico Weber     CommonFlags cf;
77e3b6d110SNico Weber     cf.CopyFrom(*common_flags());
78e3b6d110SNico Weber     cf.external_symbolizer_path = GetEnv("HWASAN_SYMBOLIZER_PATH");
79e3b6d110SNico Weber     cf.malloc_context_size = 20;
80e3b6d110SNico Weber     cf.handle_ioctl = true;
81e3b6d110SNico Weber     // FIXME: test and enable.
82e3b6d110SNico Weber     cf.check_printf = false;
83e3b6d110SNico Weber     cf.intercept_tls_get_addr = true;
84e3b6d110SNico Weber     cf.exitcode = 99;
85e3b6d110SNico Weber     // 8 shadow pages ~512kB, small enough to cover common stack sizes.
86e3b6d110SNico Weber     cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8);
87e3b6d110SNico Weber     // Sigtrap is used in error reporting.
88e3b6d110SNico Weber     cf.handle_sigtrap = kHandleSignalExclusive;
89fe195781SLeonard Chan     // For now only tested on Linux and Fuchsia. Other plantforms can be turned
90fe195781SLeonard Chan     // on as they become ready.
91fe195781SLeonard Chan     constexpr bool can_detect_leaks =
92fe195781SLeonard Chan         (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA;
93fe195781SLeonard Chan     cf.detect_leaks = cf.detect_leaks && can_detect_leaks;
94e3b6d110SNico Weber 
95e3b6d110SNico Weber #if SANITIZER_ANDROID
96e3b6d110SNico Weber     // Let platform handle other signals. It is better at reporting them then we
97e3b6d110SNico Weber     // are.
98e3b6d110SNico Weber     cf.handle_segv = kHandleSignalNo;
99e3b6d110SNico Weber     cf.handle_sigbus = kHandleSignalNo;
100e3b6d110SNico Weber     cf.handle_abort = kHandleSignalNo;
101e3b6d110SNico Weber     cf.handle_sigill = kHandleSignalNo;
102e3b6d110SNico Weber     cf.handle_sigfpe = kHandleSignalNo;
103e3b6d110SNico Weber #endif
104e3b6d110SNico Weber     OverrideCommonFlags(cf);
105e3b6d110SNico Weber   }
106e3b6d110SNico Weber 
107e3b6d110SNico Weber   Flags *f = flags();
108e3b6d110SNico Weber   f->SetDefaults();
109e3b6d110SNico Weber 
110e3b6d110SNico Weber   FlagParser parser;
111e3b6d110SNico Weber   RegisterHwasanFlags(&parser, f);
112e3b6d110SNico Weber   RegisterCommonFlags(&parser);
113e3b6d110SNico Weber 
1141cf17279SKirill Stoimenov #if CAN_SANITIZE_LEAKS
1151cf17279SKirill Stoimenov   __lsan::Flags *lf = __lsan::flags();
1161cf17279SKirill Stoimenov   lf->SetDefaults();
1171cf17279SKirill Stoimenov 
1181cf17279SKirill Stoimenov   FlagParser lsan_parser;
1191cf17279SKirill Stoimenov   __lsan::RegisterLsanFlags(&lsan_parser, lf);
1201cf17279SKirill Stoimenov   RegisterCommonFlags(&lsan_parser);
1211cf17279SKirill Stoimenov #endif
1221cf17279SKirill Stoimenov 
123e3b6d110SNico Weber #if HWASAN_CONTAINS_UBSAN
124e3b6d110SNico Weber   __ubsan::Flags *uf = __ubsan::flags();
125e3b6d110SNico Weber   uf->SetDefaults();
126e3b6d110SNico Weber 
127e3b6d110SNico Weber   FlagParser ubsan_parser;
128e3b6d110SNico Weber   __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
129e3b6d110SNico Weber   RegisterCommonFlags(&ubsan_parser);
130e3b6d110SNico Weber #endif
131e3b6d110SNico Weber 
132e3b6d110SNico Weber   // Override from user-specified string.
133e3b6d110SNico Weber   if (__hwasan_default_options)
134e3b6d110SNico Weber     parser.ParseString(__hwasan_default_options());
135ea7695dcSFangrui Song #if CAN_SANITIZE_LEAKS
136ea7695dcSFangrui Song   lsan_parser.ParseString(__lsan_default_options());
137ea7695dcSFangrui Song #endif
138e3b6d110SNico Weber #if HWASAN_CONTAINS_UBSAN
1392d7fd38cSFangrui Song   const char *ubsan_default_options = __ubsan_default_options();
140e3b6d110SNico Weber   ubsan_parser.ParseString(ubsan_default_options);
141e3b6d110SNico Weber #endif
142e3b6d110SNico Weber 
1430b1ea8cbSVitaly Buka   parser.ParseStringFromEnv("HWASAN_OPTIONS");
1441cf17279SKirill Stoimenov #if CAN_SANITIZE_LEAKS
1451cf17279SKirill Stoimenov   lsan_parser.ParseStringFromEnv("LSAN_OPTIONS");
1461cf17279SKirill Stoimenov #endif
147e3b6d110SNico Weber #if HWASAN_CONTAINS_UBSAN
1480b1ea8cbSVitaly Buka   ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
149e3b6d110SNico Weber #endif
150e3b6d110SNico Weber 
151e3b6d110SNico Weber   InitializeCommonFlags();
152e3b6d110SNico Weber 
153e3b6d110SNico Weber   if (Verbosity()) ReportUnrecognizedFlags();
154e3b6d110SNico Weber 
155e3b6d110SNico Weber   if (common_flags()->help) parser.PrintFlagDescriptions();
1561cf17279SKirill Stoimenov   // Flag validation:
1571cf17279SKirill Stoimenov   if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
1581cf17279SKirill Stoimenov     Report("%s: detect_leaks is not supported on this platform.\n",
1591cf17279SKirill Stoimenov            SanitizerToolName);
1601cf17279SKirill Stoimenov     Die();
1611cf17279SKirill Stoimenov   }
162e3b6d110SNico Weber }
163e3b6d110SNico Weber 
1642721e27cSDmitry Vyukov static void CheckUnwind() {
1652721e27cSDmitry Vyukov   GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
1662721e27cSDmitry Vyukov   stack.Print();
167e3b6d110SNico Weber }
168e3b6d110SNico Weber 
169e3b6d110SNico Weber static void HwasanFormatMemoryUsage(InternalScopedString &s) {
170e3b6d110SNico Weber   HwasanThreadList &thread_list = hwasanThreadList();
171e3b6d110SNico Weber   auto thread_stats = thread_list.GetThreadStats();
1727c1128f3SVitaly Buka   auto sds = StackDepotGetStats();
173e3b6d110SNico Weber   AllocatorStatCounters asc;
174e3b6d110SNico Weber   GetAllocatorStats(asc);
1755b7dfa96SVitaly Buka   s.AppendF(
176e3b6d110SNico Weber       "HWASAN pid: %d rss: %zd threads: %zd stacks: %zd"
177e3b6d110SNico Weber       " thr_aux: %zd stack_depot: %zd uniq_stacks: %zd"
178e3b6d110SNico Weber       " heap: %zd",
179e3b6d110SNico Weber       internal_getpid(), GetRSS(), thread_stats.n_live_threads,
180e3b6d110SNico Weber       thread_stats.total_stack_size,
181e3b6d110SNico Weber       thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(),
1827c1128f3SVitaly Buka       sds.allocated, sds.n_uniq_ids, asc[AllocatorStatMapped]);
183e3b6d110SNico Weber }
184e3b6d110SNico Weber 
185e3b6d110SNico Weber #if SANITIZER_ANDROID
186e0dadf3dSVitaly Buka static constexpr uptr kMemoryUsageBufferSize = 4096;
187e0dadf3dSVitaly Buka 
188e3b6d110SNico Weber static char *memory_usage_buffer = nullptr;
189e3b6d110SNico Weber 
190e3b6d110SNico Weber static void InitMemoryUsage() {
191e3b6d110SNico Weber   memory_usage_buffer =
192e3b6d110SNico Weber       (char *)MmapOrDie(kMemoryUsageBufferSize, "memory usage string");
193e3b6d110SNico Weber   CHECK(memory_usage_buffer);
194e3b6d110SNico Weber   memory_usage_buffer[0] = '\0';
195e3b6d110SNico Weber   DecorateMapping((uptr)memory_usage_buffer, kMemoryUsageBufferSize,
196e3b6d110SNico Weber                   memory_usage_buffer);
197e3b6d110SNico Weber }
198e3b6d110SNico Weber 
199e3b6d110SNico Weber void UpdateMemoryUsage() {
200e3b6d110SNico Weber   if (!flags()->export_memory_stats)
201e3b6d110SNico Weber     return;
202e3b6d110SNico Weber   if (!memory_usage_buffer)
203e3b6d110SNico Weber     InitMemoryUsage();
204e0dadf3dSVitaly Buka   InternalScopedString s;
205e3b6d110SNico Weber   HwasanFormatMemoryUsage(s);
206e3b6d110SNico Weber   internal_strncpy(memory_usage_buffer, s.data(), kMemoryUsageBufferSize - 1);
207e3b6d110SNico Weber   memory_usage_buffer[kMemoryUsageBufferSize - 1] = '\0';
208e3b6d110SNico Weber }
209e3b6d110SNico Weber #else
210e3b6d110SNico Weber void UpdateMemoryUsage() {}
211e3b6d110SNico Weber #endif
212e3b6d110SNico Weber 
213d4e47999SLeonard Chan void HwasanAtExit() {
214d4e47999SLeonard Chan   if (common_flags()->print_module_map)
215d4e47999SLeonard Chan     DumpProcessMap();
216d4e47999SLeonard Chan   if (flags()->print_stats && (flags()->atexit || hwasan_report_count > 0))
217d4e47999SLeonard Chan     ReportStats();
218d4e47999SLeonard Chan   if (hwasan_report_count > 0) {
219d4e47999SLeonard Chan     // ReportAtExitStatistics();
220d4e47999SLeonard Chan     if (common_flags()->exitcode)
221d4e47999SLeonard Chan       internal__exit(common_flags()->exitcode);
222d4e47999SLeonard Chan   }
223d4e47999SLeonard Chan }
224d4e47999SLeonard Chan 
225d4e47999SLeonard Chan void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,
226d4e47999SLeonard Chan                        uptr *registers_frame) {
227d4e47999SLeonard Chan   InternalMmapVector<BufferedStackTrace> stack_buffer(1);
228d4e47999SLeonard Chan   BufferedStackTrace *stack = stack_buffer.data();
229d4e47999SLeonard Chan   stack->Reset();
230d4e47999SLeonard Chan   stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal);
231d4e47999SLeonard Chan 
232d4e47999SLeonard Chan   // The second stack frame contains the failure __hwasan_check function, as
233d4e47999SLeonard Chan   // we have a stack frame for the registers saved in __hwasan_tag_mismatch that
234d4e47999SLeonard Chan   // we wish to ignore. This (currently) only occurs on AArch64, as x64
235d4e47999SLeonard Chan   // implementations use SIGTRAP to implement the failure, and thus do not go
236d4e47999SLeonard Chan   // through the stack saver.
237d4e47999SLeonard Chan   if (registers_frame && stack->trace && stack->size > 0) {
238d4e47999SLeonard Chan     stack->trace++;
239d4e47999SLeonard Chan     stack->size--;
240d4e47999SLeonard Chan   }
241d4e47999SLeonard Chan 
242d4e47999SLeonard Chan   bool fatal = flags()->halt_on_error || !ai.recover;
243d4e47999SLeonard Chan   ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store, fatal,
244d4e47999SLeonard Chan                     registers_frame);
245d4e47999SLeonard Chan }
246d4e47999SLeonard Chan 
247fba042daSAlexey Baturo void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info,
248fba042daSAlexey Baturo                        uptr *registers_frame, size_t outsize) {
249d4e47999SLeonard Chan   __hwasan::AccessInfo ai;
250d4e47999SLeonard Chan   ai.is_store = access_info & 0x10;
251d4e47999SLeonard Chan   ai.is_load = !ai.is_store;
252d4e47999SLeonard Chan   ai.recover = access_info & 0x20;
253d4e47999SLeonard Chan   ai.addr = addr;
254d4e47999SLeonard Chan   if ((access_info & 0xf) == 0xf)
255d4e47999SLeonard Chan     ai.size = outsize;
256d4e47999SLeonard Chan   else
257d4e47999SLeonard Chan     ai.size = 1 << (access_info & 0xf);
258d4e47999SLeonard Chan 
259fba042daSAlexey Baturo   HandleTagMismatch(ai, pc, frame, nullptr, registers_frame);
260d4e47999SLeonard Chan }
261d4e47999SLeonard Chan 
262c4a00ed8SLeonard Chan Thread *GetCurrentThread() {
263c4a00ed8SLeonard Chan   uptr *ThreadLongPtr = GetCurrentThreadLongPtr();
264c4a00ed8SLeonard Chan   if (UNLIKELY(*ThreadLongPtr == 0))
265c4a00ed8SLeonard Chan     return nullptr;
266c4a00ed8SLeonard Chan   auto *R = (StackAllocationsRingBuffer *)ThreadLongPtr;
267c4a00ed8SLeonard Chan   return hwasanThreadList().GetThreadByBufferAddress((uptr)R->Next());
268c4a00ed8SLeonard Chan }
269c4a00ed8SLeonard Chan 
270e3b6d110SNico Weber } // namespace __hwasan
271e3b6d110SNico Weber 
2720930643fSPeter Collingbourne using namespace __hwasan;
2730930643fSPeter Collingbourne 
2749fe3b490SJulian Lettner void __sanitizer::BufferedStackTrace::UnwindImpl(
2759fe3b490SJulian Lettner     uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
276a0884da6SJulian Lettner   Thread *t = GetCurrentThread();
277a0884da6SJulian Lettner   if (!t) {
278eaea9ed8SEvgenii Stepanov     // The thread is still being created, or has already been destroyed.
2799fe3b490SJulian Lettner     size = 0;
280a0884da6SJulian Lettner     return;
281a0884da6SJulian Lettner   }
2829b9c68a2SPeter Collingbourne   Unwind(max_depth, pc, bp, context, t->stack_top(), t->stack_bottom(),
2839b9c68a2SPeter Collingbourne          request_fast);
284a0884da6SJulian Lettner }
285a0884da6SJulian Lettner 
286e26b25f8SMitch Phillips static bool InitializeSingleGlobal(const hwasan_global &global) {
287e26b25f8SMitch Phillips   uptr full_granule_size = RoundDownTo(global.size(), 16);
288e26b25f8SMitch Phillips   TagMemoryAligned(global.addr(), full_granule_size, global.tag());
289e26b25f8SMitch Phillips   if (global.size() % 16)
290e26b25f8SMitch Phillips     TagMemoryAligned(global.addr() + full_granule_size, 16, global.size() % 16);
291e26b25f8SMitch Phillips   return false;
2920930643fSPeter Collingbourne }
2930930643fSPeter Collingbourne 
2940930643fSPeter Collingbourne static void InitLoadedGlobals() {
295dc3069daSLeonard Chan   // Fuchsia's libc provides a hook (__sanitizer_module_loaded) that runs on
296dc3069daSLeonard Chan   // the startup path which calls into __hwasan_library_loaded on all
297dc3069daSLeonard Chan   // initially loaded modules, so explicitly registering the globals here
298dc3069daSLeonard Chan   // isn't needed.
299dc3069daSLeonard Chan   if constexpr (!SANITIZER_FUCHSIA) {
3000930643fSPeter Collingbourne     dl_iterate_phdr(
301e26b25f8SMitch Phillips         [](dl_phdr_info *info, size_t /* size */, void * /* data */) -> int {
302e26b25f8SMitch Phillips           for (const hwasan_global &global : HwasanGlobalsFor(
303e26b25f8SMitch Phillips                    info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum))
304e26b25f8SMitch Phillips             InitializeSingleGlobal(global);
3050930643fSPeter Collingbourne           return 0;
3060930643fSPeter Collingbourne         },
3070930643fSPeter Collingbourne         nullptr);
3080930643fSPeter Collingbourne   }
309dc3069daSLeonard Chan }
3100930643fSPeter Collingbourne 
3110930643fSPeter Collingbourne // Prepare to run instrumented code on the main thread.
3120930643fSPeter Collingbourne static void InitInstrumentation() {
3130930643fSPeter Collingbourne   if (hwasan_instrumentation_inited) return;
3140930643fSPeter Collingbourne 
31589f778ceSLeonard Chan   InitializeOsSupport();
316d5282dfcSEvgeniy Stepanov 
3170930643fSPeter Collingbourne   if (!InitShadow()) {
3180930643fSPeter Collingbourne     Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
3190930643fSPeter Collingbourne     DumpProcessMap();
3200930643fSPeter Collingbourne     Die();
3210930643fSPeter Collingbourne   }
3220930643fSPeter Collingbourne 
3230930643fSPeter Collingbourne   InitThreads();
3240930643fSPeter Collingbourne 
3250930643fSPeter Collingbourne   hwasan_instrumentation_inited = 1;
3260930643fSPeter Collingbourne }
3270930643fSPeter Collingbourne 
3280930643fSPeter Collingbourne // Interface.
329e3b6d110SNico Weber 
330e3b6d110SNico Weber uptr __hwasan_shadow_memory_dynamic_address;  // Global interface symbol.
331e3b6d110SNico Weber 
332d11ea651SPeter Collingbourne // This function was used by the old frame descriptor mechanism. We keep it
333d11ea651SPeter Collingbourne // around to avoid breaking ABI.
334d11ea651SPeter Collingbourne void __hwasan_init_frames(uptr beg, uptr end) {}
335e3b6d110SNico Weber 
336e3b6d110SNico Weber void __hwasan_init_static() {
337e3b6d110SNico Weber   InitShadowGOT();
338e3b6d110SNico Weber   InitInstrumentation();
3390930643fSPeter Collingbourne 
3400930643fSPeter Collingbourne   // In the non-static code path we call dl_iterate_phdr here. But at this point
3410930643fSPeter Collingbourne   // libc might not have been initialized enough for dl_iterate_phdr to work.
3420930643fSPeter Collingbourne   // Fortunately, since this is a statically linked executable we can use the
3430930643fSPeter Collingbourne   // linker-defined symbol __ehdr_start to find the only relevant set of phdrs.
3440930643fSPeter Collingbourne   extern ElfW(Ehdr) __ehdr_start;
345e26b25f8SMitch Phillips   for (const hwasan_global &global : HwasanGlobalsFor(
346e26b25f8SMitch Phillips            /* base */ 0,
3470930643fSPeter Collingbourne            reinterpret_cast<const ElfW(Phdr) *>(
348e26b25f8SMitch Phillips                reinterpret_cast<const char *>(&__ehdr_start) +
349e26b25f8SMitch Phillips                __ehdr_start.e_phoff),
350e26b25f8SMitch Phillips            __ehdr_start.e_phnum))
351e26b25f8SMitch Phillips     InitializeSingleGlobal(global);
352e3b6d110SNico Weber }
353e3b6d110SNico Weber 
3540ebb7560SMitch Phillips __attribute__((constructor(0))) void __hwasan_init() {
355e3b6d110SNico Weber   CHECK(!hwasan_init_is_running);
356e3b6d110SNico Weber   if (hwasan_inited) return;
357e3b6d110SNico Weber   hwasan_init_is_running = 1;
358e3b6d110SNico Weber   SanitizerToolName = "HWAddressSanitizer";
359e3b6d110SNico Weber 
360e3b6d110SNico Weber   CacheBinaryName();
361e3b6d110SNico Weber   InitializeFlags();
362e3b6d110SNico Weber 
363e3b6d110SNico Weber   // Install tool-specific callbacks in sanitizer_common.
3642721e27cSDmitry Vyukov   SetCheckUnwindCallback(CheckUnwind);
365e3b6d110SNico Weber 
366e3b6d110SNico Weber   __sanitizer_set_report_path(common_flags()->log_path);
367e3b6d110SNico Weber 
368*a0bb2e21SVitaly Buka   InitializePlatformEarly();
369*a0bb2e21SVitaly Buka 
370e3b6d110SNico Weber   AndroidTestTlsSlot();
371e3b6d110SNico Weber 
372e3b6d110SNico Weber   DisableCoreDumperIfNecessary();
373e3b6d110SNico Weber 
374e3b6d110SNico Weber   InitInstrumentation();
3750930643fSPeter Collingbourne   InitLoadedGlobals();
376e3b6d110SNico Weber 
377e3b6d110SNico Weber   // Needs to be called here because flags()->random_tags might not have been
378e3b6d110SNico Weber   // initialized when InitInstrumentation() was called.
379846ec2c3SMatt Morehouse   GetCurrentThread()->EnsureRandomStateInited();
380e3b6d110SNico Weber 
381e3b6d110SNico Weber   SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
382e3b6d110SNico Weber   // This may call libc -> needs initialized shadow.
383e3b6d110SNico Weber   AndroidLogInit();
384e3b6d110SNico Weber 
385e3b6d110SNico Weber   InitializeInterceptors();
386e3b6d110SNico Weber   InstallDeadlySignalHandlers(HwasanOnDeadlySignal);
387e3b6d110SNico Weber   InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
388e3b6d110SNico Weber 
389e3b6d110SNico Weber   InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
390e3b6d110SNico Weber 
391e3b6d110SNico Weber   HwasanTSDInit();
392e3b6d110SNico Weber   HwasanTSDThreadInit();
393e3b6d110SNico Weber 
394e3b6d110SNico Weber   HwasanAllocatorInit();
3958a570a87SEvgenii Stepanov   HwasanInstallAtForkHandler();
396e3b6d110SNico Weber 
397f2b4b544SKirill Stoimenov   if (CAN_SANITIZE_LEAKS) {
398f2b4b544SKirill Stoimenov     __lsan::InitCommonLsan();
399f2b4b544SKirill Stoimenov     InstallAtExitCheckLeaks();
400f2b4b544SKirill Stoimenov   }
401f2b4b544SKirill Stoimenov 
402e3b6d110SNico Weber #if HWASAN_CONTAINS_UBSAN
403e3b6d110SNico Weber   __ubsan::InitAsPlugin();
404e3b6d110SNico Weber #endif
405e3b6d110SNico Weber 
4067b7db789SKirill Stoimenov   if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) {
407f2b4b544SKirill Stoimenov     __lsan::ScopedInterceptorDisabler disabler;
408f2b4b544SKirill Stoimenov     Symbolizer::LateInitialize();
409f2b4b544SKirill Stoimenov   }
410f2b4b544SKirill Stoimenov 
411e3b6d110SNico Weber   VPrintf(1, "HWAddressSanitizer init done\n");
412e3b6d110SNico Weber 
413e3b6d110SNico Weber   hwasan_init_is_running = 0;
414e3b6d110SNico Weber   hwasan_inited = 1;
415e3b6d110SNico Weber }
416e3b6d110SNico Weber 
4170930643fSPeter Collingbourne void __hwasan_library_loaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
4180930643fSPeter Collingbourne                              ElfW(Half) phnum) {
419e26b25f8SMitch Phillips   for (const hwasan_global &global : HwasanGlobalsFor(base, phdr, phnum))
420e26b25f8SMitch Phillips     InitializeSingleGlobal(global);
4210930643fSPeter Collingbourne }
4220930643fSPeter Collingbourne 
4230930643fSPeter Collingbourne void __hwasan_library_unloaded(ElfW(Addr) base, const ElfW(Phdr) * phdr,
4240930643fSPeter Collingbourne                                ElfW(Half) phnum) {
4250930643fSPeter Collingbourne   for (; phnum != 0; ++phdr, --phnum)
4260930643fSPeter Collingbourne     if (phdr->p_type == PT_LOAD)
4270930643fSPeter Collingbourne       TagMemory(base + phdr->p_vaddr, phdr->p_memsz, 0);
4280930643fSPeter Collingbourne }
4290930643fSPeter Collingbourne 
430e3b6d110SNico Weber void __hwasan_print_shadow(const void *p, uptr sz) {
431e3b6d110SNico Weber   uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
432e3b6d110SNico Weber   uptr shadow_first = MemToShadow(ptr_raw);
433e3b6d110SNico Weber   uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
434e3b6d110SNico Weber   Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw,
435e3b6d110SNico Weber          ptr_raw + sz, GetTagFromPointer((uptr)p));
4368c60e0b6SMatt Morehouse   for (uptr s = shadow_first; s <= shadow_last; ++s) {
4378c60e0b6SMatt Morehouse     tag_t mem_tag = *reinterpret_cast<tag_t *>(s);
4388c60e0b6SMatt Morehouse     uptr granule_addr = ShadowToMem(s);
4398c60e0b6SMatt Morehouse     if (mem_tag && mem_tag < kShadowAlignment)
4408c60e0b6SMatt Morehouse       Printf("  %zx: %02x(%02x)\n", granule_addr, mem_tag,
4418c60e0b6SMatt Morehouse              *reinterpret_cast<tag_t *>(granule_addr + kShadowAlignment - 1));
4428c60e0b6SMatt Morehouse     else
4438c60e0b6SMatt Morehouse       Printf("  %zx: %02x\n", granule_addr, mem_tag);
4448c60e0b6SMatt Morehouse   }
445e3b6d110SNico Weber }
446e3b6d110SNico Weber 
447e3b6d110SNico Weber sptr __hwasan_test_shadow(const void *p, uptr sz) {
448e3b6d110SNico Weber   if (sz == 0)
449e3b6d110SNico Weber     return -1;
4505a5bf053SVitaly Buka   uptr ptr = reinterpret_cast<uptr>(p);
4515a5bf053SVitaly Buka   tag_t ptr_tag = GetTagFromPointer(ptr);
4525a5bf053SVitaly Buka   uptr ptr_raw = UntagAddr(ptr);
453e3b6d110SNico Weber   uptr shadow_first = MemToShadow(ptr_raw);
4545a5bf053SVitaly Buka   uptr shadow_last = MemToShadow(ptr_raw + sz);
4555a5bf053SVitaly Buka   for (uptr s = shadow_first; s < shadow_last; ++s) {
4565a5bf053SVitaly Buka     if (UNLIKELY(*(tag_t *)s != ptr_tag)) {
4575a5bf053SVitaly Buka       uptr short_size =
4585a5bf053SVitaly Buka           ShortTagSize(*(tag_t *)s, AddTagToPointer(ShadowToMem(s), ptr_tag));
4595a5bf053SVitaly Buka       sptr offset = ShadowToMem(s) - ptr_raw + short_size;
460e3b6d110SNico Weber       return offset < 0 ? 0 : offset;
461e3b6d110SNico Weber     }
4625a5bf053SVitaly Buka   }
4635a5bf053SVitaly Buka 
4645a5bf053SVitaly Buka   uptr end = ptr + sz;
4655a5bf053SVitaly Buka   uptr tail_sz = end & (kShadowAlignment - 1);
4665a5bf053SVitaly Buka   if (!tail_sz)
467e3b6d110SNico Weber     return -1;
4685a5bf053SVitaly Buka 
4695a5bf053SVitaly Buka   uptr short_size =
4705a5bf053SVitaly Buka       ShortTagSize(*(tag_t *)shadow_last, end & ~(kShadowAlignment - 1));
4715a5bf053SVitaly Buka   if (LIKELY(tail_sz <= short_size))
4725a5bf053SVitaly Buka     return -1;
4735a5bf053SVitaly Buka 
4745a5bf053SVitaly Buka   sptr offset = sz - tail_sz + short_size;
4755a5bf053SVitaly Buka   return offset < 0 ? 0 : offset;
476e3b6d110SNico Weber }
477e3b6d110SNico Weber 
478e3b6d110SNico Weber u16 __sanitizer_unaligned_load16(const uu16 *p) {
479e3b6d110SNico Weber   return *p;
480e3b6d110SNico Weber }
481e3b6d110SNico Weber u32 __sanitizer_unaligned_load32(const uu32 *p) {
482e3b6d110SNico Weber   return *p;
483e3b6d110SNico Weber }
484e3b6d110SNico Weber u64 __sanitizer_unaligned_load64(const uu64 *p) {
485e3b6d110SNico Weber   return *p;
486e3b6d110SNico Weber }
487e3b6d110SNico Weber void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
488e3b6d110SNico Weber   *p = x;
489e3b6d110SNico Weber }
490e3b6d110SNico Weber void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
491e3b6d110SNico Weber   *p = x;
492e3b6d110SNico Weber }
493e3b6d110SNico Weber void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
494e3b6d110SNico Weber   *p = x;
495e3b6d110SNico Weber }
496e3b6d110SNico Weber 
497e3b6d110SNico Weber void __hwasan_loadN(uptr p, uptr sz) {
498e3b6d110SNico Weber   CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
499e3b6d110SNico Weber }
500e3b6d110SNico Weber void __hwasan_load1(uptr p) {
501e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p);
502e3b6d110SNico Weber }
503e3b6d110SNico Weber void __hwasan_load2(uptr p) {
504e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p);
505e3b6d110SNico Weber }
506e3b6d110SNico Weber void __hwasan_load4(uptr p) {
507e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p);
508e3b6d110SNico Weber }
509e3b6d110SNico Weber void __hwasan_load8(uptr p) {
510e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p);
511e3b6d110SNico Weber }
512e3b6d110SNico Weber void __hwasan_load16(uptr p) {
513e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p);
514e3b6d110SNico Weber }
515e3b6d110SNico Weber 
516e3b6d110SNico Weber void __hwasan_loadN_noabort(uptr p, uptr sz) {
517e3b6d110SNico Weber   CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz);
518e3b6d110SNico Weber }
519e3b6d110SNico Weber void __hwasan_load1_noabort(uptr p) {
520e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p);
521e3b6d110SNico Weber }
522e3b6d110SNico Weber void __hwasan_load2_noabort(uptr p) {
523e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p);
524e3b6d110SNico Weber }
525e3b6d110SNico Weber void __hwasan_load4_noabort(uptr p) {
526e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p);
527e3b6d110SNico Weber }
528e3b6d110SNico Weber void __hwasan_load8_noabort(uptr p) {
529e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p);
530e3b6d110SNico Weber }
531e3b6d110SNico Weber void __hwasan_load16_noabort(uptr p) {
532e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p);
533e3b6d110SNico Weber }
534e3b6d110SNico Weber 
535b33dcc5bSEnna1 void __hwasan_loadN_match_all(uptr p, uptr sz, u8 match_all_tag) {
536b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
537b33dcc5bSEnna1     CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
538b33dcc5bSEnna1 }
539b33dcc5bSEnna1 void __hwasan_load1_match_all(uptr p, u8 match_all_tag) {
540b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
541b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p);
542b33dcc5bSEnna1 }
543b33dcc5bSEnna1 void __hwasan_load2_match_all(uptr p, u8 match_all_tag) {
544b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
545b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p);
546b33dcc5bSEnna1 }
547b33dcc5bSEnna1 void __hwasan_load4_match_all(uptr p, u8 match_all_tag) {
548b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
549b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p);
550b33dcc5bSEnna1 }
551b33dcc5bSEnna1 void __hwasan_load8_match_all(uptr p, u8 match_all_tag) {
552b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
553b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p);
554b33dcc5bSEnna1 }
555b33dcc5bSEnna1 void __hwasan_load16_match_all(uptr p, u8 match_all_tag) {
556b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
557b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p);
558b33dcc5bSEnna1 }
559b33dcc5bSEnna1 
560b33dcc5bSEnna1 void __hwasan_loadN_match_all_noabort(uptr p, uptr sz, u8 match_all_tag) {
561b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
562b33dcc5bSEnna1     CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz);
563b33dcc5bSEnna1 }
564b33dcc5bSEnna1 void __hwasan_load1_match_all_noabort(uptr p, u8 match_all_tag) {
565b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
566b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p);
567b33dcc5bSEnna1 }
568b33dcc5bSEnna1 void __hwasan_load2_match_all_noabort(uptr p, u8 match_all_tag) {
569b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
570b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p);
571b33dcc5bSEnna1 }
572b33dcc5bSEnna1 void __hwasan_load4_match_all_noabort(uptr p, u8 match_all_tag) {
573b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
574b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p);
575b33dcc5bSEnna1 }
576b33dcc5bSEnna1 void __hwasan_load8_match_all_noabort(uptr p, u8 match_all_tag) {
577b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
578b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p);
579b33dcc5bSEnna1 }
580b33dcc5bSEnna1 void __hwasan_load16_match_all_noabort(uptr p, u8 match_all_tag) {
581b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
582b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p);
583b33dcc5bSEnna1 }
584b33dcc5bSEnna1 
585e3b6d110SNico Weber void __hwasan_storeN(uptr p, uptr sz) {
586e3b6d110SNico Weber   CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz);
587e3b6d110SNico Weber }
588e3b6d110SNico Weber void __hwasan_store1(uptr p) {
589e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p);
590e3b6d110SNico Weber }
591e3b6d110SNico Weber void __hwasan_store2(uptr p) {
592e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p);
593e3b6d110SNico Weber }
594e3b6d110SNico Weber void __hwasan_store4(uptr p) {
595e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p);
596e3b6d110SNico Weber }
597e3b6d110SNico Weber void __hwasan_store8(uptr p) {
598e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p);
599e3b6d110SNico Weber }
600e3b6d110SNico Weber void __hwasan_store16(uptr p) {
601e3b6d110SNico Weber   CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p);
602e3b6d110SNico Weber }
603e3b6d110SNico Weber 
604e3b6d110SNico Weber void __hwasan_storeN_noabort(uptr p, uptr sz) {
605e3b6d110SNico Weber   CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz);
606e3b6d110SNico Weber }
607e3b6d110SNico Weber void __hwasan_store1_noabort(uptr p) {
608e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p);
609e3b6d110SNico Weber }
610e3b6d110SNico Weber void __hwasan_store2_noabort(uptr p) {
611e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p);
612e3b6d110SNico Weber }
613e3b6d110SNico Weber void __hwasan_store4_noabort(uptr p) {
614e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p);
615e3b6d110SNico Weber }
616e3b6d110SNico Weber void __hwasan_store8_noabort(uptr p) {
617e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p);
618e3b6d110SNico Weber }
619e3b6d110SNico Weber void __hwasan_store16_noabort(uptr p) {
620e3b6d110SNico Weber   CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
621e3b6d110SNico Weber }
622e3b6d110SNico Weber 
623b33dcc5bSEnna1 void __hwasan_storeN_match_all(uptr p, uptr sz, u8 match_all_tag) {
624b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
625b33dcc5bSEnna1     CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz);
626b33dcc5bSEnna1 }
627b33dcc5bSEnna1 void __hwasan_store1_match_all(uptr p, u8 match_all_tag) {
628b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
629b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p);
630b33dcc5bSEnna1 }
631b33dcc5bSEnna1 void __hwasan_store2_match_all(uptr p, u8 match_all_tag) {
632b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
633b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p);
634b33dcc5bSEnna1 }
635b33dcc5bSEnna1 void __hwasan_store4_match_all(uptr p, u8 match_all_tag) {
636b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
637b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p);
638b33dcc5bSEnna1 }
639b33dcc5bSEnna1 void __hwasan_store8_match_all(uptr p, u8 match_all_tag) {
640b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
641b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p);
642b33dcc5bSEnna1 }
643b33dcc5bSEnna1 void __hwasan_store16_match_all(uptr p, u8 match_all_tag) {
644b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
645b33dcc5bSEnna1     CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p);
646b33dcc5bSEnna1 }
647b33dcc5bSEnna1 
648b33dcc5bSEnna1 void __hwasan_storeN_match_all_noabort(uptr p, uptr sz, u8 match_all_tag) {
649b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
650b33dcc5bSEnna1     CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz);
651b33dcc5bSEnna1 }
652b33dcc5bSEnna1 void __hwasan_store1_match_all_noabort(uptr p, u8 match_all_tag) {
653b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
654b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p);
655b33dcc5bSEnna1 }
656b33dcc5bSEnna1 void __hwasan_store2_match_all_noabort(uptr p, u8 match_all_tag) {
657b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
658b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p);
659b33dcc5bSEnna1 }
660b33dcc5bSEnna1 void __hwasan_store4_match_all_noabort(uptr p, u8 match_all_tag) {
661b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
662b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p);
663b33dcc5bSEnna1 }
664b33dcc5bSEnna1 void __hwasan_store8_match_all_noabort(uptr p, u8 match_all_tag) {
665b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
666b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p);
667b33dcc5bSEnna1 }
668b33dcc5bSEnna1 void __hwasan_store16_match_all_noabort(uptr p, u8 match_all_tag) {
669b33dcc5bSEnna1   if (GetTagFromPointer(p) != match_all_tag)
670b33dcc5bSEnna1     CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
671b33dcc5bSEnna1 }
672b33dcc5bSEnna1 
673e3b6d110SNico Weber void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
6746ad91fcbSVitaly Buka   TagMemoryAligned(UntagAddr(p), sz, tag);
675e3b6d110SNico Weber }
676e3b6d110SNico Weber 
677e3b6d110SNico Weber uptr __hwasan_tag_pointer(uptr p, u8 tag) {
678e3b6d110SNico Weber   return AddTagToPointer(p, tag);
679e3b6d110SNico Weber }
680e3b6d110SNico Weber 
68164fa90bfSVitaly Buka u8 __hwasan_get_tag_from_pointer(uptr p) { return GetTagFromPointer(p); }
68264fa90bfSVitaly Buka 
683e3b6d110SNico Weber void __hwasan_handle_longjmp(const void *sp_dst) {
684e3b6d110SNico Weber   uptr dst = (uptr)sp_dst;
685e3b6d110SNico Weber   // HWASan does not support tagged SP.
686f031fc35SVitaly Buka   CHECK_EQ(GetTagFromPointer(dst), 0);
687e3b6d110SNico Weber 
688e3b6d110SNico Weber   uptr sp = (uptr)__builtin_frame_address(0);
689e3b6d110SNico Weber   static const uptr kMaxExpectedCleanupSize = 64 << 20;  // 64M
690e3b6d110SNico Weber   if (dst < sp || dst - sp > kMaxExpectedCleanupSize) {
691e3b6d110SNico Weber     Report(
692e3b6d110SNico Weber         "WARNING: HWASan is ignoring requested __hwasan_handle_longjmp: "
693e3b6d110SNico Weber         "stack top: %p; target %p; distance: %p (%zd)\n"
694e3b6d110SNico Weber         "False positive error reports may follow\n",
6950673fb6eSThurston Dang         (void *)sp, (void *)dst, dst - sp, dst - sp);
696e3b6d110SNico Weber     return;
697e3b6d110SNico Weber   }
698e3b6d110SNico Weber   TagMemory(sp, dst - sp, 0);
699e3b6d110SNico Weber }
700e3b6d110SNico Weber 
701f46a52b5SEvgeniy Stepanov void __hwasan_handle_vfork(const void *sp_dst) {
702f46a52b5SEvgeniy Stepanov   uptr sp = (uptr)sp_dst;
703f46a52b5SEvgeniy Stepanov   Thread *t = GetCurrentThread();
704f46a52b5SEvgeniy Stepanov   CHECK(t);
705f46a52b5SEvgeniy Stepanov   uptr top = t->stack_top();
706f46a52b5SEvgeniy Stepanov   uptr bottom = t->stack_bottom();
707ecb2c1fdSEvgeniy Stepanov   if (top == 0 || bottom == 0 || sp < bottom || sp >= top) {
708f46a52b5SEvgeniy Stepanov     Report(
709f46a52b5SEvgeniy Stepanov         "WARNING: HWASan is ignoring requested __hwasan_handle_vfork: "
710f46a52b5SEvgeniy Stepanov         "stack top: %zx; current %zx; bottom: %zx \n"
711f46a52b5SEvgeniy Stepanov         "False positive error reports may follow\n",
712f46a52b5SEvgeniy Stepanov         top, sp, bottom);
713f46a52b5SEvgeniy Stepanov     return;
714f46a52b5SEvgeniy Stepanov   }
715f46a52b5SEvgeniy Stepanov   TagMemory(bottom, sp - bottom, 0);
716f46a52b5SEvgeniy Stepanov }
717f46a52b5SEvgeniy Stepanov 
718f46a52b5SEvgeniy Stepanov extern "C" void *__hwasan_extra_spill_area() {
719f46a52b5SEvgeniy Stepanov   Thread *t = GetCurrentThread();
720f46a52b5SEvgeniy Stepanov   return &t->vfork_spill();
721f46a52b5SEvgeniy Stepanov }
722f46a52b5SEvgeniy Stepanov 
723e3b6d110SNico Weber void __hwasan_print_memory_usage() {
724e0dadf3dSVitaly Buka   InternalScopedString s;
725e3b6d110SNico Weber   HwasanFormatMemoryUsage(s);
726e3b6d110SNico Weber   Printf("%s\n", s.data());
727e3b6d110SNico Weber }
728e3b6d110SNico Weber 
729493565a4SMatt Morehouse static const u8 kFallbackTag = 0xBB & kTagMask;
730e3b6d110SNico Weber 
731e3b6d110SNico Weber u8 __hwasan_generate_tag() {
732e3b6d110SNico Weber   Thread *t = GetCurrentThread();
733e3b6d110SNico Weber   if (!t) return kFallbackTag;
734e3b6d110SNico Weber   return t->GenerateRandomTag();
735e3b6d110SNico Weber }
736e3b6d110SNico Weber 
73721f72c05SLeonard Chan void __hwasan_add_frame_record(u64 frame_record_info) {
73821f72c05SLeonard Chan   Thread *t = GetCurrentThread();
73921f72c05SLeonard Chan   if (t)
74021f72c05SLeonard Chan     t->stack_allocations()->push(frame_record_info);
74121f72c05SLeonard Chan }
74221f72c05SLeonard Chan 
743e3b6d110SNico Weber #if !SANITIZER_SUPPORTS_WEAK_HOOKS
744e3b6d110SNico Weber extern "C" {
745e3b6d110SNico Weber SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
746e3b6d110SNico Weber const char* __hwasan_default_options() { return ""; }
747e3b6d110SNico Weber }  // extern "C"
748e3b6d110SNico Weber #endif
749e3b6d110SNico Weber 
750e3b6d110SNico Weber extern "C" {
751e3b6d110SNico Weber SANITIZER_INTERFACE_ATTRIBUTE
752e3b6d110SNico Weber void __sanitizer_print_stack_trace() {
753e3b6d110SNico Weber   GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());
754e3b6d110SNico Weber   stack.Print();
755e3b6d110SNico Weber }
756d564cfb5SLeonard Chan 
757d564cfb5SLeonard Chan // Entry point for interoperability between __hwasan_tag_mismatch (ASM) and the
758d564cfb5SLeonard Chan // rest of the mismatch handling code (C++).
759d564cfb5SLeonard Chan void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame,
760d564cfb5SLeonard Chan                             size_t outsize) {
761fba042daSAlexey Baturo   __hwasan::HwasanTagMismatch(addr, (uptr)__builtin_return_address(0),
762fba042daSAlexey Baturo                               (uptr)__builtin_frame_address(0), access_info,
763fba042daSAlexey Baturo                               registers_frame, outsize);
764d564cfb5SLeonard Chan }
765d564cfb5SLeonard Chan 
766e3b6d110SNico Weber } // extern "C"
767