168d75effSDimitry Andric //===-- sanitizer_common.cpp ----------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is shared between AddressSanitizer and ThreadSanitizer 1068d75effSDimitry Andric // run-time libraries. 1168d75effSDimitry Andric //===----------------------------------------------------------------------===// 1268d75effSDimitry Andric 1368d75effSDimitry Andric #include "sanitizer_common.h" 1481ad6265SDimitry Andric 1568d75effSDimitry Andric #include "sanitizer_allocator_interface.h" 1668d75effSDimitry Andric #include "sanitizer_allocator_internal.h" 1768d75effSDimitry Andric #include "sanitizer_atomic.h" 1868d75effSDimitry Andric #include "sanitizer_flags.h" 1981ad6265SDimitry Andric #include "sanitizer_interface_internal.h" 2068d75effSDimitry Andric #include "sanitizer_libc.h" 2168d75effSDimitry Andric #include "sanitizer_placement_new.h" 2268d75effSDimitry Andric 2368d75effSDimitry Andric namespace __sanitizer { 2468d75effSDimitry Andric 2568d75effSDimitry Andric const char *SanitizerToolName = "SanitizerTool"; 2668d75effSDimitry Andric 2768d75effSDimitry Andric atomic_uint32_t current_verbosity; 2868d75effSDimitry Andric uptr PageSizeCached; 2968d75effSDimitry Andric u32 NumberOfCPUsCached; 3068d75effSDimitry Andric 3168d75effSDimitry Andric // PID of the tracer task in StopTheWorld. It shares the address space with the 3268d75effSDimitry Andric // main process, but has a different PID and thus requires special handling. 3368d75effSDimitry Andric uptr stoptheworld_tracer_pid = 0; 3468d75effSDimitry Andric // Cached pid of parent process - if the parent process dies, we want to keep 3568d75effSDimitry Andric // writing to the same log file. 3668d75effSDimitry Andric uptr stoptheworld_tracer_ppid = 0; 3768d75effSDimitry Andric 3868d75effSDimitry Andric void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, 3968d75effSDimitry Andric const char *mmap_type, error_t err, 4068d75effSDimitry Andric bool raw_report) { 4168d75effSDimitry Andric static int recursion_count; 42fe6060f1SDimitry Andric if (raw_report || recursion_count) { 43fe6060f1SDimitry Andric // If raw report is requested or we went into recursion just die. The 44fe6060f1SDimitry Andric // Report() and CHECK calls below may call mmap recursively and fail. 4568d75effSDimitry Andric RawWrite("ERROR: Failed to mmap\n"); 4668d75effSDimitry Andric Die(); 4768d75effSDimitry Andric } 4868d75effSDimitry Andric recursion_count++; 4981ad6265SDimitry Andric if (ErrorIsOOM(err)) { 5081ad6265SDimitry Andric ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n", 5181ad6265SDimitry Andric mmap_type, size, size, mem_type, err); 5281ad6265SDimitry Andric } else { 5381ad6265SDimitry Andric Report( 5481ad6265SDimitry Andric "ERROR: %s failed to " 5568d75effSDimitry Andric "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", 5668d75effSDimitry Andric SanitizerToolName, mmap_type, size, size, mem_type, err); 5781ad6265SDimitry Andric } 5868d75effSDimitry Andric #if !SANITIZER_GO 5968d75effSDimitry Andric DumpProcessMap(); 6068d75effSDimitry Andric #endif 6168d75effSDimitry Andric UNREACHABLE("unable to mmap"); 6268d75effSDimitry Andric } 6368d75effSDimitry Andric 6406c3fb27SDimitry Andric void NORETURN ReportMunmapFailureAndDie(void *addr, uptr size, error_t err, 6506c3fb27SDimitry Andric bool raw_report) { 6606c3fb27SDimitry Andric static int recursion_count; 6706c3fb27SDimitry Andric if (raw_report || recursion_count) { 6806c3fb27SDimitry Andric // If raw report is requested or we went into recursion just die. The 6906c3fb27SDimitry Andric // Report() and CHECK calls below may call munmap recursively and fail. 7006c3fb27SDimitry Andric RawWrite("ERROR: Failed to munmap\n"); 7106c3fb27SDimitry Andric Die(); 7206c3fb27SDimitry Andric } 7306c3fb27SDimitry Andric recursion_count++; 7406c3fb27SDimitry Andric Report( 7506c3fb27SDimitry Andric "ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p (error " 7606c3fb27SDimitry Andric "code: %d)\n", 7706c3fb27SDimitry Andric SanitizerToolName, size, size, addr, err); 7806c3fb27SDimitry Andric #if !SANITIZER_GO 7906c3fb27SDimitry Andric DumpProcessMap(); 8006c3fb27SDimitry Andric #endif 8106c3fb27SDimitry Andric UNREACHABLE("unable to unmmap"); 8206c3fb27SDimitry Andric } 8306c3fb27SDimitry Andric 8468d75effSDimitry Andric typedef bool UptrComparisonFunction(const uptr &a, const uptr &b); 8568d75effSDimitry Andric typedef bool U32ComparisonFunction(const u32 &a, const u32 &b); 8668d75effSDimitry Andric 8768d75effSDimitry Andric const char *StripPathPrefix(const char *filepath, 8868d75effSDimitry Andric const char *strip_path_prefix) { 8968d75effSDimitry Andric if (!filepath) return nullptr; 9068d75effSDimitry Andric if (!strip_path_prefix) return filepath; 9168d75effSDimitry Andric const char *res = filepath; 9268d75effSDimitry Andric if (const char *pos = internal_strstr(filepath, strip_path_prefix)) 9368d75effSDimitry Andric res = pos + internal_strlen(strip_path_prefix); 9468d75effSDimitry Andric if (res[0] == '.' && res[1] == '/') 9568d75effSDimitry Andric res += 2; 9668d75effSDimitry Andric return res; 9768d75effSDimitry Andric } 9868d75effSDimitry Andric 9968d75effSDimitry Andric const char *StripModuleName(const char *module) { 10068d75effSDimitry Andric if (!module) 10168d75effSDimitry Andric return nullptr; 10268d75effSDimitry Andric if (SANITIZER_WINDOWS) { 10368d75effSDimitry Andric // On Windows, both slash and backslash are possible. 10468d75effSDimitry Andric // Pick the one that goes last. 10568d75effSDimitry Andric if (const char *bslash_pos = internal_strrchr(module, '\\')) 10668d75effSDimitry Andric return StripModuleName(bslash_pos + 1); 10768d75effSDimitry Andric } 10868d75effSDimitry Andric if (const char *slash_pos = internal_strrchr(module, '/')) { 10968d75effSDimitry Andric return slash_pos + 1; 11068d75effSDimitry Andric } 11168d75effSDimitry Andric return module; 11268d75effSDimitry Andric } 11368d75effSDimitry Andric 11468d75effSDimitry Andric void ReportErrorSummary(const char *error_message, const char *alt_tool_name) { 11568d75effSDimitry Andric if (!common_flags()->print_summary) 11668d75effSDimitry Andric return; 117fe6060f1SDimitry Andric InternalScopedString buff; 1185f757f3fSDimitry Andric buff.AppendF("SUMMARY: %s: %s", 1195f757f3fSDimitry Andric alt_tool_name ? alt_tool_name : SanitizerToolName, 1205f757f3fSDimitry Andric error_message); 12168d75effSDimitry Andric __sanitizer_report_error_summary(buff.data()); 12268d75effSDimitry Andric } 12368d75effSDimitry Andric 12468d75effSDimitry Andric // Removes the ANSI escape sequences from the input string (in-place). 12568d75effSDimitry Andric void RemoveANSIEscapeSequencesFromString(char *str) { 12668d75effSDimitry Andric if (!str) 12768d75effSDimitry Andric return; 12868d75effSDimitry Andric 12968d75effSDimitry Andric // We are going to remove the escape sequences in place. 13068d75effSDimitry Andric char *s = str; 13168d75effSDimitry Andric char *z = str; 13268d75effSDimitry Andric while (*s != '\0') { 13368d75effSDimitry Andric CHECK_GE(s, z); 13468d75effSDimitry Andric // Skip over ANSI escape sequences with pointer 's'. 13568d75effSDimitry Andric if (*s == '\033' && *(s + 1) == '[') { 13668d75effSDimitry Andric s = internal_strchrnul(s, 'm'); 13768d75effSDimitry Andric if (*s == '\0') { 13868d75effSDimitry Andric break; 13968d75effSDimitry Andric } 14068d75effSDimitry Andric s++; 14168d75effSDimitry Andric continue; 14268d75effSDimitry Andric } 14368d75effSDimitry Andric // 's' now points at a character we want to keep. Copy over the buffer 14468d75effSDimitry Andric // content if the escape sequence has been perviously skipped andadvance 14568d75effSDimitry Andric // both pointers. 14668d75effSDimitry Andric if (s != z) 14768d75effSDimitry Andric *z = *s; 14868d75effSDimitry Andric 14968d75effSDimitry Andric // If we have not seen an escape sequence, just advance both pointers. 15068d75effSDimitry Andric z++; 15168d75effSDimitry Andric s++; 15268d75effSDimitry Andric } 15368d75effSDimitry Andric 15468d75effSDimitry Andric // Null terminate the string. 15568d75effSDimitry Andric *z = '\0'; 15668d75effSDimitry Andric } 15768d75effSDimitry Andric 15868d75effSDimitry Andric void LoadedModule::set(const char *module_name, uptr base_address) { 15968d75effSDimitry Andric clear(); 16068d75effSDimitry Andric full_name_ = internal_strdup(module_name); 16168d75effSDimitry Andric base_address_ = base_address; 16268d75effSDimitry Andric } 16368d75effSDimitry Andric 16468d75effSDimitry Andric void LoadedModule::set(const char *module_name, uptr base_address, 16568d75effSDimitry Andric ModuleArch arch, u8 uuid[kModuleUUIDSize], 16668d75effSDimitry Andric bool instrumented) { 16768d75effSDimitry Andric set(module_name, base_address); 16868d75effSDimitry Andric arch_ = arch; 16968d75effSDimitry Andric internal_memcpy(uuid_, uuid, sizeof(uuid_)); 1700eae32dcSDimitry Andric uuid_size_ = kModuleUUIDSize; 17168d75effSDimitry Andric instrumented_ = instrumented; 17268d75effSDimitry Andric } 17368d75effSDimitry Andric 1740eae32dcSDimitry Andric void LoadedModule::setUuid(const char *uuid, uptr size) { 1750eae32dcSDimitry Andric if (size > kModuleUUIDSize) 1760eae32dcSDimitry Andric size = kModuleUUIDSize; 1770eae32dcSDimitry Andric internal_memcpy(uuid_, uuid, size); 1780eae32dcSDimitry Andric uuid_size_ = size; 1790eae32dcSDimitry Andric } 1800eae32dcSDimitry Andric 18168d75effSDimitry Andric void LoadedModule::clear() { 18268d75effSDimitry Andric InternalFree(full_name_); 18368d75effSDimitry Andric base_address_ = 0; 18481ad6265SDimitry Andric max_address_ = 0; 18568d75effSDimitry Andric full_name_ = nullptr; 18668d75effSDimitry Andric arch_ = kModuleArchUnknown; 18768d75effSDimitry Andric internal_memset(uuid_, 0, kModuleUUIDSize); 18868d75effSDimitry Andric instrumented_ = false; 18968d75effSDimitry Andric while (!ranges_.empty()) { 19068d75effSDimitry Andric AddressRange *r = ranges_.front(); 19168d75effSDimitry Andric ranges_.pop_front(); 19268d75effSDimitry Andric InternalFree(r); 19368d75effSDimitry Andric } 19468d75effSDimitry Andric } 19568d75effSDimitry Andric 19668d75effSDimitry Andric void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable, 19768d75effSDimitry Andric bool writable, const char *name) { 19868d75effSDimitry Andric void *mem = InternalAlloc(sizeof(AddressRange)); 19968d75effSDimitry Andric AddressRange *r = 20068d75effSDimitry Andric new(mem) AddressRange(beg, end, executable, writable, name); 20168d75effSDimitry Andric ranges_.push_back(r); 20281ad6265SDimitry Andric max_address_ = Max(max_address_, end); 20368d75effSDimitry Andric } 20468d75effSDimitry Andric 20568d75effSDimitry Andric bool LoadedModule::containsAddress(uptr address) const { 20668d75effSDimitry Andric for (const AddressRange &r : ranges()) { 20768d75effSDimitry Andric if (r.beg <= address && address < r.end) 20868d75effSDimitry Andric return true; 20968d75effSDimitry Andric } 21068d75effSDimitry Andric return false; 21168d75effSDimitry Andric } 21268d75effSDimitry Andric 21368d75effSDimitry Andric static atomic_uintptr_t g_total_mmaped; 21468d75effSDimitry Andric 21568d75effSDimitry Andric void IncreaseTotalMmap(uptr size) { 21668d75effSDimitry Andric if (!common_flags()->mmap_limit_mb) return; 21768d75effSDimitry Andric uptr total_mmaped = 21868d75effSDimitry Andric atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size; 21968d75effSDimitry Andric // Since for now mmap_limit_mb is not a user-facing flag, just kill 22068d75effSDimitry Andric // a program. Use RAW_CHECK to avoid extra mmaps in reporting. 22168d75effSDimitry Andric RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb); 22268d75effSDimitry Andric } 22368d75effSDimitry Andric 22468d75effSDimitry Andric void DecreaseTotalMmap(uptr size) { 22568d75effSDimitry Andric if (!common_flags()->mmap_limit_mb) return; 22668d75effSDimitry Andric atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed); 22768d75effSDimitry Andric } 22868d75effSDimitry Andric 22968d75effSDimitry Andric bool TemplateMatch(const char *templ, const char *str) { 23068d75effSDimitry Andric if ((!str) || str[0] == 0) 23168d75effSDimitry Andric return false; 23268d75effSDimitry Andric bool start = false; 23368d75effSDimitry Andric if (templ && templ[0] == '^') { 23468d75effSDimitry Andric start = true; 23568d75effSDimitry Andric templ++; 23668d75effSDimitry Andric } 23768d75effSDimitry Andric bool asterisk = false; 23868d75effSDimitry Andric while (templ && templ[0]) { 23968d75effSDimitry Andric if (templ[0] == '*') { 24068d75effSDimitry Andric templ++; 24168d75effSDimitry Andric start = false; 24268d75effSDimitry Andric asterisk = true; 24368d75effSDimitry Andric continue; 24468d75effSDimitry Andric } 24568d75effSDimitry Andric if (templ[0] == '$') 24668d75effSDimitry Andric return str[0] == 0 || asterisk; 24768d75effSDimitry Andric if (str[0] == 0) 24868d75effSDimitry Andric return false; 24968d75effSDimitry Andric char *tpos = (char*)internal_strchr(templ, '*'); 25068d75effSDimitry Andric char *tpos1 = (char*)internal_strchr(templ, '$'); 25168d75effSDimitry Andric if ((!tpos) || (tpos1 && tpos1 < tpos)) 25268d75effSDimitry Andric tpos = tpos1; 25368d75effSDimitry Andric if (tpos) 25468d75effSDimitry Andric tpos[0] = 0; 25568d75effSDimitry Andric const char *str0 = str; 25668d75effSDimitry Andric const char *spos = internal_strstr(str, templ); 25768d75effSDimitry Andric str = spos + internal_strlen(templ); 25868d75effSDimitry Andric templ = tpos; 25968d75effSDimitry Andric if (tpos) 26068d75effSDimitry Andric tpos[0] = tpos == tpos1 ? '$' : '*'; 26168d75effSDimitry Andric if (!spos) 26268d75effSDimitry Andric return false; 26368d75effSDimitry Andric if (start && spos != str0) 26468d75effSDimitry Andric return false; 26568d75effSDimitry Andric start = false; 26668d75effSDimitry Andric asterisk = false; 26768d75effSDimitry Andric } 26868d75effSDimitry Andric return true; 26968d75effSDimitry Andric } 27068d75effSDimitry Andric 27168d75effSDimitry Andric static char binary_name_cache_str[kMaxPathLength]; 27268d75effSDimitry Andric static char process_name_cache_str[kMaxPathLength]; 27368d75effSDimitry Andric 27468d75effSDimitry Andric const char *GetProcessName() { 27568d75effSDimitry Andric return process_name_cache_str; 27668d75effSDimitry Andric } 27768d75effSDimitry Andric 27868d75effSDimitry Andric static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) { 27968d75effSDimitry Andric ReadLongProcessName(buf, buf_len); 28068d75effSDimitry Andric char *s = const_cast<char *>(StripModuleName(buf)); 28168d75effSDimitry Andric uptr len = internal_strlen(s); 28268d75effSDimitry Andric if (s != buf) { 28368d75effSDimitry Andric internal_memmove(buf, s, len); 28468d75effSDimitry Andric buf[len] = '\0'; 28568d75effSDimitry Andric } 28668d75effSDimitry Andric return len; 28768d75effSDimitry Andric } 28868d75effSDimitry Andric 28968d75effSDimitry Andric void UpdateProcessName() { 29068d75effSDimitry Andric ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); 29168d75effSDimitry Andric } 29268d75effSDimitry Andric 29368d75effSDimitry Andric // Call once to make sure that binary_name_cache_str is initialized 29468d75effSDimitry Andric void CacheBinaryName() { 29568d75effSDimitry Andric if (binary_name_cache_str[0] != '\0') 29668d75effSDimitry Andric return; 29768d75effSDimitry Andric ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str)); 29868d75effSDimitry Andric ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); 29968d75effSDimitry Andric } 30068d75effSDimitry Andric 30168d75effSDimitry Andric uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) { 30268d75effSDimitry Andric CacheBinaryName(); 30368d75effSDimitry Andric uptr name_len = internal_strlen(binary_name_cache_str); 30468d75effSDimitry Andric name_len = (name_len < buf_len - 1) ? name_len : buf_len - 1; 30568d75effSDimitry Andric if (buf_len == 0) 30668d75effSDimitry Andric return 0; 30768d75effSDimitry Andric internal_memcpy(buf, binary_name_cache_str, name_len); 30868d75effSDimitry Andric buf[name_len] = '\0'; 30968d75effSDimitry Andric return name_len; 31068d75effSDimitry Andric } 31168d75effSDimitry Andric 312fe6060f1SDimitry Andric uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) { 313fe6060f1SDimitry Andric ReadBinaryNameCached(buf, buf_len); 314fe6060f1SDimitry Andric const char *exec_name_pos = StripModuleName(buf); 315fe6060f1SDimitry Andric uptr name_len = exec_name_pos - buf; 316fe6060f1SDimitry Andric buf[name_len] = '\0'; 317fe6060f1SDimitry Andric return name_len; 318fe6060f1SDimitry Andric } 319fe6060f1SDimitry Andric 3205ffd83dbSDimitry Andric #if !SANITIZER_GO 32168d75effSDimitry Andric void PrintCmdline() { 32268d75effSDimitry Andric char **argv = GetArgv(); 32368d75effSDimitry Andric if (!argv) return; 32468d75effSDimitry Andric Printf("\nCommand: "); 32568d75effSDimitry Andric for (uptr i = 0; argv[i]; ++i) 32668d75effSDimitry Andric Printf("%s ", argv[i]); 32768d75effSDimitry Andric Printf("\n\n"); 32868d75effSDimitry Andric } 3295ffd83dbSDimitry Andric #endif 33068d75effSDimitry Andric 33168d75effSDimitry Andric // Malloc hooks. 33268d75effSDimitry Andric static const int kMaxMallocFreeHooks = 5; 33368d75effSDimitry Andric struct MallocFreeHook { 33468d75effSDimitry Andric void (*malloc_hook)(const void *, uptr); 33568d75effSDimitry Andric void (*free_hook)(const void *); 33668d75effSDimitry Andric }; 33768d75effSDimitry Andric 33868d75effSDimitry Andric static MallocFreeHook MFHooks[kMaxMallocFreeHooks]; 33968d75effSDimitry Andric 34081ad6265SDimitry Andric void RunMallocHooks(void *ptr, uptr size) { 34181ad6265SDimitry Andric __sanitizer_malloc_hook(ptr, size); 34268d75effSDimitry Andric for (int i = 0; i < kMaxMallocFreeHooks; i++) { 34368d75effSDimitry Andric auto hook = MFHooks[i].malloc_hook; 34481ad6265SDimitry Andric if (!hook) 34581ad6265SDimitry Andric break; 34668d75effSDimitry Andric hook(ptr, size); 34768d75effSDimitry Andric } 34868d75effSDimitry Andric } 34968d75effSDimitry Andric 350*0fca6ea1SDimitry Andric // Returns '1' if the call to free() should be ignored (based on 351*0fca6ea1SDimitry Andric // __sanitizer_ignore_free_hook), or '0' otherwise. 352*0fca6ea1SDimitry Andric int RunFreeHooks(void *ptr) { 353*0fca6ea1SDimitry Andric if (__sanitizer_ignore_free_hook(ptr)) { 354*0fca6ea1SDimitry Andric return 1; 355*0fca6ea1SDimitry Andric } 356*0fca6ea1SDimitry Andric 35781ad6265SDimitry Andric __sanitizer_free_hook(ptr); 35868d75effSDimitry Andric for (int i = 0; i < kMaxMallocFreeHooks; i++) { 35968d75effSDimitry Andric auto hook = MFHooks[i].free_hook; 36081ad6265SDimitry Andric if (!hook) 36181ad6265SDimitry Andric break; 36268d75effSDimitry Andric hook(ptr); 36368d75effSDimitry Andric } 364*0fca6ea1SDimitry Andric 365*0fca6ea1SDimitry Andric return 0; 36668d75effSDimitry Andric } 36768d75effSDimitry Andric 36868d75effSDimitry Andric static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr), 36968d75effSDimitry Andric void (*free_hook)(const void *)) { 37068d75effSDimitry Andric if (!malloc_hook || !free_hook) return 0; 37168d75effSDimitry Andric for (int i = 0; i < kMaxMallocFreeHooks; i++) { 37268d75effSDimitry Andric if (MFHooks[i].malloc_hook == nullptr) { 37368d75effSDimitry Andric MFHooks[i].malloc_hook = malloc_hook; 37468d75effSDimitry Andric MFHooks[i].free_hook = free_hook; 37568d75effSDimitry Andric return i + 1; 37668d75effSDimitry Andric } 37768d75effSDimitry Andric } 37868d75effSDimitry Andric return 0; 37968d75effSDimitry Andric } 38068d75effSDimitry Andric 381fe6060f1SDimitry Andric void internal_sleep(unsigned seconds) { 382fe6060f1SDimitry Andric internal_usleep((u64)seconds * 1000 * 1000); 383fe6060f1SDimitry Andric } 384fe6060f1SDimitry Andric void SleepForSeconds(unsigned seconds) { 385fe6060f1SDimitry Andric internal_usleep((u64)seconds * 1000 * 1000); 386fe6060f1SDimitry Andric } 387fe6060f1SDimitry Andric void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); } 388fe6060f1SDimitry Andric 38981ad6265SDimitry Andric void WaitForDebugger(unsigned seconds, const char *label) { 39081ad6265SDimitry Andric if (seconds) { 39181ad6265SDimitry Andric Report("Sleeping for %u second(s) %s\n", seconds, label); 39281ad6265SDimitry Andric SleepForSeconds(seconds); 39381ad6265SDimitry Andric } 39481ad6265SDimitry Andric } 39581ad6265SDimitry Andric 39668d75effSDimitry Andric } // namespace __sanitizer 39768d75effSDimitry Andric 39868d75effSDimitry Andric using namespace __sanitizer; 39968d75effSDimitry Andric 40068d75effSDimitry Andric extern "C" { 40168d75effSDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary, 40268d75effSDimitry Andric const char *error_summary) { 40368d75effSDimitry Andric Printf("%s\n", error_summary); 40468d75effSDimitry Andric } 40568d75effSDimitry Andric 40668d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 40768d75effSDimitry Andric int __sanitizer_acquire_crash_state() { 40868d75effSDimitry Andric static atomic_uint8_t in_crash_state = {}; 40968d75effSDimitry Andric return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed); 41068d75effSDimitry Andric } 41168d75effSDimitry Andric 41268d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 41368d75effSDimitry Andric int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *, 41468d75effSDimitry Andric uptr), 41568d75effSDimitry Andric void (*free_hook)(const void *)) { 41668d75effSDimitry Andric return InstallMallocFreeHooks(malloc_hook, free_hook); 41768d75effSDimitry Andric } 41881ad6265SDimitry Andric 41981ad6265SDimitry Andric // Provide default (no-op) implementation of malloc hooks. 42081ad6265SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, void *ptr, 42181ad6265SDimitry Andric uptr size) { 42281ad6265SDimitry Andric (void)ptr; 42381ad6265SDimitry Andric (void)size; 42481ad6265SDimitry Andric } 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) { 42781ad6265SDimitry Andric (void)ptr; 42881ad6265SDimitry Andric } 42981ad6265SDimitry Andric 430*0fca6ea1SDimitry Andric SANITIZER_INTERFACE_WEAK_DEF(int, __sanitizer_ignore_free_hook, void *ptr) { 431*0fca6ea1SDimitry Andric (void)ptr; 432*0fca6ea1SDimitry Andric return 0; 433*0fca6ea1SDimitry Andric } 434*0fca6ea1SDimitry Andric 43568d75effSDimitry Andric } // extern "C" 436