xref: /openbsd-src/gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- sanitizer_common.cpp ----------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is shared between AddressSanitizer and ThreadSanitizer
103cab2bb3Spatrick // run-time libraries.
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick 
133cab2bb3Spatrick #include "sanitizer_common.h"
14*810390e3Srobert 
153cab2bb3Spatrick #include "sanitizer_allocator_interface.h"
163cab2bb3Spatrick #include "sanitizer_allocator_internal.h"
173cab2bb3Spatrick #include "sanitizer_atomic.h"
183cab2bb3Spatrick #include "sanitizer_flags.h"
19*810390e3Srobert #include "sanitizer_interface_internal.h"
203cab2bb3Spatrick #include "sanitizer_libc.h"
213cab2bb3Spatrick #include "sanitizer_placement_new.h"
223cab2bb3Spatrick 
233cab2bb3Spatrick namespace __sanitizer {
243cab2bb3Spatrick 
253cab2bb3Spatrick const char *SanitizerToolName = "SanitizerTool";
263cab2bb3Spatrick 
273cab2bb3Spatrick atomic_uint32_t current_verbosity;
283cab2bb3Spatrick uptr PageSizeCached;
293cab2bb3Spatrick u32 NumberOfCPUsCached;
303cab2bb3Spatrick 
313cab2bb3Spatrick // PID of the tracer task in StopTheWorld. It shares the address space with the
323cab2bb3Spatrick // main process, but has a different PID and thus requires special handling.
333cab2bb3Spatrick uptr stoptheworld_tracer_pid = 0;
343cab2bb3Spatrick // Cached pid of parent process - if the parent process dies, we want to keep
353cab2bb3Spatrick // writing to the same log file.
363cab2bb3Spatrick uptr stoptheworld_tracer_ppid = 0;
373cab2bb3Spatrick 
ReportMmapFailureAndDie(uptr size,const char * mem_type,const char * mmap_type,error_t err,bool raw_report)383cab2bb3Spatrick void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
393cab2bb3Spatrick                                       const char *mmap_type, error_t err,
403cab2bb3Spatrick                                       bool raw_report) {
413cab2bb3Spatrick   static int recursion_count;
42d89ec533Spatrick   if (raw_report || recursion_count) {
43d89ec533Spatrick     // If raw report is requested or we went into recursion just die.  The
44d89ec533Spatrick     // Report() and CHECK calls below may call mmap recursively and fail.
453cab2bb3Spatrick     RawWrite("ERROR: Failed to mmap\n");
463cab2bb3Spatrick     Die();
473cab2bb3Spatrick   }
483cab2bb3Spatrick   recursion_count++;
49*810390e3Srobert   if (ErrorIsOOM(err)) {
50*810390e3Srobert     ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n",
51*810390e3Srobert               mmap_type, size, size, mem_type, err);
52*810390e3Srobert   } else {
53*810390e3Srobert     Report(
54*810390e3Srobert         "ERROR: %s failed to "
553cab2bb3Spatrick         "%s 0x%zx (%zd) bytes of %s (error code: %d)\n",
563cab2bb3Spatrick         SanitizerToolName, mmap_type, size, size, mem_type, err);
57*810390e3Srobert   }
583cab2bb3Spatrick #if !SANITIZER_GO
593cab2bb3Spatrick   DumpProcessMap();
603cab2bb3Spatrick #endif
613cab2bb3Spatrick   UNREACHABLE("unable to mmap");
623cab2bb3Spatrick }
633cab2bb3Spatrick 
643cab2bb3Spatrick typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
653cab2bb3Spatrick typedef bool U32ComparisonFunction(const u32 &a, const u32 &b);
663cab2bb3Spatrick 
StripPathPrefix(const char * filepath,const char * strip_path_prefix)673cab2bb3Spatrick const char *StripPathPrefix(const char *filepath,
683cab2bb3Spatrick                             const char *strip_path_prefix) {
693cab2bb3Spatrick   if (!filepath) return nullptr;
703cab2bb3Spatrick   if (!strip_path_prefix) return filepath;
713cab2bb3Spatrick   const char *res = filepath;
723cab2bb3Spatrick   if (const char *pos = internal_strstr(filepath, strip_path_prefix))
733cab2bb3Spatrick     res = pos + internal_strlen(strip_path_prefix);
743cab2bb3Spatrick   if (res[0] == '.' && res[1] == '/')
753cab2bb3Spatrick     res += 2;
763cab2bb3Spatrick   return res;
773cab2bb3Spatrick }
783cab2bb3Spatrick 
StripModuleName(const char * module)793cab2bb3Spatrick const char *StripModuleName(const char *module) {
803cab2bb3Spatrick   if (!module)
813cab2bb3Spatrick     return nullptr;
823cab2bb3Spatrick   if (SANITIZER_WINDOWS) {
833cab2bb3Spatrick     // On Windows, both slash and backslash are possible.
843cab2bb3Spatrick     // Pick the one that goes last.
853cab2bb3Spatrick     if (const char *bslash_pos = internal_strrchr(module, '\\'))
863cab2bb3Spatrick       return StripModuleName(bslash_pos + 1);
873cab2bb3Spatrick   }
883cab2bb3Spatrick   if (const char *slash_pos = internal_strrchr(module, '/')) {
893cab2bb3Spatrick     return slash_pos + 1;
903cab2bb3Spatrick   }
913cab2bb3Spatrick   return module;
923cab2bb3Spatrick }
933cab2bb3Spatrick 
ReportErrorSummary(const char * error_message,const char * alt_tool_name)943cab2bb3Spatrick void ReportErrorSummary(const char *error_message, const char *alt_tool_name) {
953cab2bb3Spatrick   if (!common_flags()->print_summary)
963cab2bb3Spatrick     return;
97d89ec533Spatrick   InternalScopedString buff;
983cab2bb3Spatrick   buff.append("SUMMARY: %s: %s",
993cab2bb3Spatrick               alt_tool_name ? alt_tool_name : SanitizerToolName, error_message);
1003cab2bb3Spatrick   __sanitizer_report_error_summary(buff.data());
1013cab2bb3Spatrick }
1023cab2bb3Spatrick 
1033cab2bb3Spatrick // Removes the ANSI escape sequences from the input string (in-place).
RemoveANSIEscapeSequencesFromString(char * str)1043cab2bb3Spatrick void RemoveANSIEscapeSequencesFromString(char *str) {
1053cab2bb3Spatrick   if (!str)
1063cab2bb3Spatrick     return;
1073cab2bb3Spatrick 
1083cab2bb3Spatrick   // We are going to remove the escape sequences in place.
1093cab2bb3Spatrick   char *s = str;
1103cab2bb3Spatrick   char *z = str;
1113cab2bb3Spatrick   while (*s != '\0') {
1123cab2bb3Spatrick     CHECK_GE(s, z);
1133cab2bb3Spatrick     // Skip over ANSI escape sequences with pointer 's'.
1143cab2bb3Spatrick     if (*s == '\033' && *(s + 1) == '[') {
1153cab2bb3Spatrick       s = internal_strchrnul(s, 'm');
1163cab2bb3Spatrick       if (*s == '\0') {
1173cab2bb3Spatrick         break;
1183cab2bb3Spatrick       }
1193cab2bb3Spatrick       s++;
1203cab2bb3Spatrick       continue;
1213cab2bb3Spatrick     }
1223cab2bb3Spatrick     // 's' now points at a character we want to keep. Copy over the buffer
1233cab2bb3Spatrick     // content if the escape sequence has been perviously skipped andadvance
1243cab2bb3Spatrick     // both pointers.
1253cab2bb3Spatrick     if (s != z)
1263cab2bb3Spatrick       *z = *s;
1273cab2bb3Spatrick 
1283cab2bb3Spatrick     // If we have not seen an escape sequence, just advance both pointers.
1293cab2bb3Spatrick     z++;
1303cab2bb3Spatrick     s++;
1313cab2bb3Spatrick   }
1323cab2bb3Spatrick 
1333cab2bb3Spatrick   // Null terminate the string.
1343cab2bb3Spatrick   *z = '\0';
1353cab2bb3Spatrick }
1363cab2bb3Spatrick 
set(const char * module_name,uptr base_address)1373cab2bb3Spatrick void LoadedModule::set(const char *module_name, uptr base_address) {
1383cab2bb3Spatrick   clear();
1393cab2bb3Spatrick   full_name_ = internal_strdup(module_name);
1403cab2bb3Spatrick   base_address_ = base_address;
1413cab2bb3Spatrick }
1423cab2bb3Spatrick 
set(const char * module_name,uptr base_address,ModuleArch arch,u8 uuid[kModuleUUIDSize],bool instrumented)1433cab2bb3Spatrick void LoadedModule::set(const char *module_name, uptr base_address,
1443cab2bb3Spatrick                        ModuleArch arch, u8 uuid[kModuleUUIDSize],
1453cab2bb3Spatrick                        bool instrumented) {
1463cab2bb3Spatrick   set(module_name, base_address);
1473cab2bb3Spatrick   arch_ = arch;
1483cab2bb3Spatrick   internal_memcpy(uuid_, uuid, sizeof(uuid_));
149*810390e3Srobert   uuid_size_ = kModuleUUIDSize;
1503cab2bb3Spatrick   instrumented_ = instrumented;
1513cab2bb3Spatrick }
1523cab2bb3Spatrick 
setUuid(const char * uuid,uptr size)153*810390e3Srobert void LoadedModule::setUuid(const char *uuid, uptr size) {
154*810390e3Srobert   if (size > kModuleUUIDSize)
155*810390e3Srobert     size = kModuleUUIDSize;
156*810390e3Srobert   internal_memcpy(uuid_, uuid, size);
157*810390e3Srobert   uuid_size_ = size;
158*810390e3Srobert }
159*810390e3Srobert 
clear()1603cab2bb3Spatrick void LoadedModule::clear() {
1613cab2bb3Spatrick   InternalFree(full_name_);
1623cab2bb3Spatrick   base_address_ = 0;
163*810390e3Srobert   max_address_ = 0;
1643cab2bb3Spatrick   full_name_ = nullptr;
1653cab2bb3Spatrick   arch_ = kModuleArchUnknown;
1663cab2bb3Spatrick   internal_memset(uuid_, 0, kModuleUUIDSize);
1673cab2bb3Spatrick   instrumented_ = false;
1683cab2bb3Spatrick   while (!ranges_.empty()) {
1693cab2bb3Spatrick     AddressRange *r = ranges_.front();
1703cab2bb3Spatrick     ranges_.pop_front();
1713cab2bb3Spatrick     InternalFree(r);
1723cab2bb3Spatrick   }
1733cab2bb3Spatrick }
1743cab2bb3Spatrick 
addAddressRange(uptr beg,uptr end,bool executable,bool writable,const char * name)1753cab2bb3Spatrick void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable,
1763cab2bb3Spatrick                                    bool writable, const char *name) {
1773cab2bb3Spatrick   void *mem = InternalAlloc(sizeof(AddressRange));
1783cab2bb3Spatrick   AddressRange *r =
1793cab2bb3Spatrick       new(mem) AddressRange(beg, end, executable, writable, name);
1803cab2bb3Spatrick   ranges_.push_back(r);
181*810390e3Srobert   max_address_ = Max(max_address_, end);
1823cab2bb3Spatrick }
1833cab2bb3Spatrick 
containsAddress(uptr address) const1843cab2bb3Spatrick bool LoadedModule::containsAddress(uptr address) const {
1853cab2bb3Spatrick   for (const AddressRange &r : ranges()) {
1863cab2bb3Spatrick     if (r.beg <= address && address < r.end)
1873cab2bb3Spatrick       return true;
1883cab2bb3Spatrick   }
1893cab2bb3Spatrick   return false;
1903cab2bb3Spatrick }
1913cab2bb3Spatrick 
1923cab2bb3Spatrick static atomic_uintptr_t g_total_mmaped;
1933cab2bb3Spatrick 
IncreaseTotalMmap(uptr size)1943cab2bb3Spatrick void IncreaseTotalMmap(uptr size) {
1953cab2bb3Spatrick   if (!common_flags()->mmap_limit_mb) return;
1963cab2bb3Spatrick   uptr total_mmaped =
1973cab2bb3Spatrick       atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size;
1983cab2bb3Spatrick   // Since for now mmap_limit_mb is not a user-facing flag, just kill
1993cab2bb3Spatrick   // a program. Use RAW_CHECK to avoid extra mmaps in reporting.
2003cab2bb3Spatrick   RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb);
2013cab2bb3Spatrick }
2023cab2bb3Spatrick 
DecreaseTotalMmap(uptr size)2033cab2bb3Spatrick void DecreaseTotalMmap(uptr size) {
2043cab2bb3Spatrick   if (!common_flags()->mmap_limit_mb) return;
2053cab2bb3Spatrick   atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
2063cab2bb3Spatrick }
2073cab2bb3Spatrick 
TemplateMatch(const char * templ,const char * str)2083cab2bb3Spatrick bool TemplateMatch(const char *templ, const char *str) {
2093cab2bb3Spatrick   if ((!str) || str[0] == 0)
2103cab2bb3Spatrick     return false;
2113cab2bb3Spatrick   bool start = false;
2123cab2bb3Spatrick   if (templ && templ[0] == '^') {
2133cab2bb3Spatrick     start = true;
2143cab2bb3Spatrick     templ++;
2153cab2bb3Spatrick   }
2163cab2bb3Spatrick   bool asterisk = false;
2173cab2bb3Spatrick   while (templ && templ[0]) {
2183cab2bb3Spatrick     if (templ[0] == '*') {
2193cab2bb3Spatrick       templ++;
2203cab2bb3Spatrick       start = false;
2213cab2bb3Spatrick       asterisk = true;
2223cab2bb3Spatrick       continue;
2233cab2bb3Spatrick     }
2243cab2bb3Spatrick     if (templ[0] == '$')
2253cab2bb3Spatrick       return str[0] == 0 || asterisk;
2263cab2bb3Spatrick     if (str[0] == 0)
2273cab2bb3Spatrick       return false;
2283cab2bb3Spatrick     char *tpos = (char*)internal_strchr(templ, '*');
2293cab2bb3Spatrick     char *tpos1 = (char*)internal_strchr(templ, '$');
2303cab2bb3Spatrick     if ((!tpos) || (tpos1 && tpos1 < tpos))
2313cab2bb3Spatrick       tpos = tpos1;
2323cab2bb3Spatrick     if (tpos)
2333cab2bb3Spatrick       tpos[0] = 0;
2343cab2bb3Spatrick     const char *str0 = str;
2353cab2bb3Spatrick     const char *spos = internal_strstr(str, templ);
2363cab2bb3Spatrick     str = spos + internal_strlen(templ);
2373cab2bb3Spatrick     templ = tpos;
2383cab2bb3Spatrick     if (tpos)
2393cab2bb3Spatrick       tpos[0] = tpos == tpos1 ? '$' : '*';
2403cab2bb3Spatrick     if (!spos)
2413cab2bb3Spatrick       return false;
2423cab2bb3Spatrick     if (start && spos != str0)
2433cab2bb3Spatrick       return false;
2443cab2bb3Spatrick     start = false;
2453cab2bb3Spatrick     asterisk = false;
2463cab2bb3Spatrick   }
2473cab2bb3Spatrick   return true;
2483cab2bb3Spatrick }
2493cab2bb3Spatrick 
2503cab2bb3Spatrick static char binary_name_cache_str[kMaxPathLength];
2513cab2bb3Spatrick static char process_name_cache_str[kMaxPathLength];
2523cab2bb3Spatrick 
GetProcessName()2533cab2bb3Spatrick const char *GetProcessName() {
2543cab2bb3Spatrick   return process_name_cache_str;
2553cab2bb3Spatrick }
2563cab2bb3Spatrick 
ReadProcessName(char * buf,uptr buf_len)2573cab2bb3Spatrick static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) {
2583cab2bb3Spatrick   ReadLongProcessName(buf, buf_len);
2593cab2bb3Spatrick   char *s = const_cast<char *>(StripModuleName(buf));
2603cab2bb3Spatrick   uptr len = internal_strlen(s);
2613cab2bb3Spatrick   if (s != buf) {
2623cab2bb3Spatrick     internal_memmove(buf, s, len);
2633cab2bb3Spatrick     buf[len] = '\0';
2643cab2bb3Spatrick   }
2653cab2bb3Spatrick   return len;
2663cab2bb3Spatrick }
2673cab2bb3Spatrick 
UpdateProcessName()2683cab2bb3Spatrick void UpdateProcessName() {
2693cab2bb3Spatrick   ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
2703cab2bb3Spatrick }
2713cab2bb3Spatrick 
2723cab2bb3Spatrick // Call once to make sure that binary_name_cache_str is initialized
CacheBinaryName()2733cab2bb3Spatrick void CacheBinaryName() {
2743cab2bb3Spatrick   if (binary_name_cache_str[0] != '\0')
2753cab2bb3Spatrick     return;
2763cab2bb3Spatrick   ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str));
2773cab2bb3Spatrick   ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str));
2783cab2bb3Spatrick }
2793cab2bb3Spatrick 
ReadBinaryNameCached(char * buf,uptr buf_len)2803cab2bb3Spatrick uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) {
2813cab2bb3Spatrick   CacheBinaryName();
2823cab2bb3Spatrick   uptr name_len = internal_strlen(binary_name_cache_str);
2833cab2bb3Spatrick   name_len = (name_len < buf_len - 1) ? name_len : buf_len - 1;
2843cab2bb3Spatrick   if (buf_len == 0)
2853cab2bb3Spatrick     return 0;
2863cab2bb3Spatrick   internal_memcpy(buf, binary_name_cache_str, name_len);
2873cab2bb3Spatrick   buf[name_len] = '\0';
2883cab2bb3Spatrick   return name_len;
2893cab2bb3Spatrick }
2903cab2bb3Spatrick 
ReadBinaryDir(char * buf,uptr buf_len)291d89ec533Spatrick uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) {
292d89ec533Spatrick   ReadBinaryNameCached(buf, buf_len);
293d89ec533Spatrick   const char *exec_name_pos = StripModuleName(buf);
294d89ec533Spatrick   uptr name_len = exec_name_pos - buf;
295d89ec533Spatrick   buf[name_len] = '\0';
296d89ec533Spatrick   return name_len;
297d89ec533Spatrick }
298d89ec533Spatrick 
2991f9cb04fSpatrick #if !SANITIZER_GO
PrintCmdline()3003cab2bb3Spatrick void PrintCmdline() {
3013cab2bb3Spatrick   char **argv = GetArgv();
3023cab2bb3Spatrick   if (!argv) return;
3033cab2bb3Spatrick   Printf("\nCommand: ");
3043cab2bb3Spatrick   for (uptr i = 0; argv[i]; ++i)
3053cab2bb3Spatrick     Printf("%s ", argv[i]);
3063cab2bb3Spatrick   Printf("\n\n");
3073cab2bb3Spatrick }
3081f9cb04fSpatrick #endif
3093cab2bb3Spatrick 
3103cab2bb3Spatrick // Malloc hooks.
3113cab2bb3Spatrick static const int kMaxMallocFreeHooks = 5;
3123cab2bb3Spatrick struct MallocFreeHook {
3133cab2bb3Spatrick   void (*malloc_hook)(const void *, uptr);
3143cab2bb3Spatrick   void (*free_hook)(const void *);
3153cab2bb3Spatrick };
3163cab2bb3Spatrick 
3173cab2bb3Spatrick static MallocFreeHook MFHooks[kMaxMallocFreeHooks];
3183cab2bb3Spatrick 
RunMallocHooks(void * ptr,uptr size)319*810390e3Srobert void RunMallocHooks(void *ptr, uptr size) {
320*810390e3Srobert   __sanitizer_malloc_hook(ptr, size);
3213cab2bb3Spatrick   for (int i = 0; i < kMaxMallocFreeHooks; i++) {
3223cab2bb3Spatrick     auto hook = MFHooks[i].malloc_hook;
323*810390e3Srobert     if (!hook)
324*810390e3Srobert       break;
3253cab2bb3Spatrick     hook(ptr, size);
3263cab2bb3Spatrick   }
3273cab2bb3Spatrick }
3283cab2bb3Spatrick 
RunFreeHooks(void * ptr)329*810390e3Srobert void RunFreeHooks(void *ptr) {
330*810390e3Srobert   __sanitizer_free_hook(ptr);
3313cab2bb3Spatrick   for (int i = 0; i < kMaxMallocFreeHooks; i++) {
3323cab2bb3Spatrick     auto hook = MFHooks[i].free_hook;
333*810390e3Srobert     if (!hook)
334*810390e3Srobert       break;
3353cab2bb3Spatrick     hook(ptr);
3363cab2bb3Spatrick   }
3373cab2bb3Spatrick }
3383cab2bb3Spatrick 
InstallMallocFreeHooks(void (* malloc_hook)(const void *,uptr),void (* free_hook)(const void *))3393cab2bb3Spatrick static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
3403cab2bb3Spatrick                                   void (*free_hook)(const void *)) {
3413cab2bb3Spatrick   if (!malloc_hook || !free_hook) return 0;
3423cab2bb3Spatrick   for (int i = 0; i < kMaxMallocFreeHooks; i++) {
3433cab2bb3Spatrick     if (MFHooks[i].malloc_hook == nullptr) {
3443cab2bb3Spatrick       MFHooks[i].malloc_hook = malloc_hook;
3453cab2bb3Spatrick       MFHooks[i].free_hook = free_hook;
3463cab2bb3Spatrick       return i + 1;
3473cab2bb3Spatrick     }
3483cab2bb3Spatrick   }
3493cab2bb3Spatrick   return 0;
3503cab2bb3Spatrick }
3513cab2bb3Spatrick 
internal_sleep(unsigned seconds)352d89ec533Spatrick void internal_sleep(unsigned seconds) {
353d89ec533Spatrick   internal_usleep((u64)seconds * 1000 * 1000);
354d89ec533Spatrick }
SleepForSeconds(unsigned seconds)355d89ec533Spatrick void SleepForSeconds(unsigned seconds) {
356d89ec533Spatrick   internal_usleep((u64)seconds * 1000 * 1000);
357d89ec533Spatrick }
SleepForMillis(unsigned millis)358d89ec533Spatrick void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); }
359d89ec533Spatrick 
WaitForDebugger(unsigned seconds,const char * label)360*810390e3Srobert void WaitForDebugger(unsigned seconds, const char *label) {
361*810390e3Srobert   if (seconds) {
362*810390e3Srobert     Report("Sleeping for %u second(s) %s\n", seconds, label);
363*810390e3Srobert     SleepForSeconds(seconds);
364*810390e3Srobert   }
365*810390e3Srobert }
366*810390e3Srobert 
3673cab2bb3Spatrick } // namespace __sanitizer
3683cab2bb3Spatrick 
3693cab2bb3Spatrick using namespace __sanitizer;
3703cab2bb3Spatrick 
3713cab2bb3Spatrick extern "C" {
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_report_error_summary,const char * error_summary)3723cab2bb3Spatrick SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
3733cab2bb3Spatrick                              const char *error_summary) {
3743cab2bb3Spatrick   Printf("%s\n", error_summary);
3753cab2bb3Spatrick }
3763cab2bb3Spatrick 
3773cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_acquire_crash_state()3783cab2bb3Spatrick int __sanitizer_acquire_crash_state() {
3793cab2bb3Spatrick   static atomic_uint8_t in_crash_state = {};
3803cab2bb3Spatrick   return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed);
3813cab2bb3Spatrick }
3823cab2bb3Spatrick 
3833cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_install_malloc_and_free_hooks(void (* malloc_hook)(const void *,uptr),void (* free_hook)(const void *))3843cab2bb3Spatrick int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *,
3853cab2bb3Spatrick                                                                   uptr),
3863cab2bb3Spatrick                                               void (*free_hook)(const void *)) {
3873cab2bb3Spatrick   return InstallMallocFreeHooks(malloc_hook, free_hook);
3883cab2bb3Spatrick }
389*810390e3Srobert 
390*810390e3Srobert // Provide default (no-op) implementation of malloc hooks.
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_malloc_hook,void * ptr,uptr size)391*810390e3Srobert SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, void *ptr,
392*810390e3Srobert                              uptr size) {
393*810390e3Srobert   (void)ptr;
394*810390e3Srobert   (void)size;
395*810390e3Srobert }
396*810390e3Srobert 
SANITIZER_INTERFACE_WEAK_DEF(void,__sanitizer_free_hook,void * ptr)397*810390e3Srobert SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {
398*810390e3Srobert   (void)ptr;
399*810390e3Srobert }
400*810390e3Srobert 
4013cab2bb3Spatrick } // extern "C"
402