1 1.1 mrg //===-- sanitizer_common.cpp ----------------------------------------------===// 2 1.1 mrg // 3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 mrg // 7 1.1 mrg //===----------------------------------------------------------------------===// 8 1.1 mrg // 9 1.1 mrg // This file is shared between AddressSanitizer and ThreadSanitizer 10 1.1 mrg // run-time libraries. 11 1.1 mrg //===----------------------------------------------------------------------===// 12 1.1 mrg 13 1.1 mrg #include "sanitizer_common.h" 14 1.4 mrg 15 1.1 mrg #include "sanitizer_allocator_interface.h" 16 1.1 mrg #include "sanitizer_allocator_internal.h" 17 1.1 mrg #include "sanitizer_atomic.h" 18 1.1 mrg #include "sanitizer_flags.h" 19 1.4 mrg #include "sanitizer_interface_internal.h" 20 1.1 mrg #include "sanitizer_libc.h" 21 1.1 mrg #include "sanitizer_placement_new.h" 22 1.1 mrg 23 1.1 mrg namespace __sanitizer { 24 1.1 mrg 25 1.1 mrg const char *SanitizerToolName = "SanitizerTool"; 26 1.1 mrg 27 1.1 mrg atomic_uint32_t current_verbosity; 28 1.1 mrg uptr PageSizeCached; 29 1.1 mrg u32 NumberOfCPUsCached; 30 1.1 mrg 31 1.1 mrg // PID of the tracer task in StopTheWorld. It shares the address space with the 32 1.1 mrg // main process, but has a different PID and thus requires special handling. 33 1.1 mrg uptr stoptheworld_tracer_pid = 0; 34 1.1 mrg // Cached pid of parent process - if the parent process dies, we want to keep 35 1.1 mrg // writing to the same log file. 36 1.1 mrg uptr stoptheworld_tracer_ppid = 0; 37 1.1 mrg 38 1.1 mrg void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, 39 1.1 mrg const char *mmap_type, error_t err, 40 1.1 mrg bool raw_report) { 41 1.1 mrg static int recursion_count; 42 1.3 mrg if (raw_report || recursion_count) { 43 1.3 mrg // If raw report is requested or we went into recursion just die. The 44 1.3 mrg // Report() and CHECK calls below may call mmap recursively and fail. 45 1.1 mrg RawWrite("ERROR: Failed to mmap\n"); 46 1.1 mrg Die(); 47 1.1 mrg } 48 1.1 mrg recursion_count++; 49 1.4 mrg if (ErrorIsOOM(err)) { 50 1.4 mrg ERROR_OOM("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n", 51 1.4 mrg mmap_type, size, size, mem_type, err); 52 1.4 mrg } else { 53 1.4 mrg Report( 54 1.4 mrg "ERROR: %s failed to " 55 1.4 mrg "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", 56 1.4 mrg SanitizerToolName, mmap_type, size, size, mem_type, err); 57 1.4 mrg } 58 1.1 mrg #if !SANITIZER_GO 59 1.1 mrg DumpProcessMap(); 60 1.1 mrg #endif 61 1.1 mrg UNREACHABLE("unable to mmap"); 62 1.1 mrg } 63 1.1 mrg 64 1.4 mrg void NORETURN ReportMunmapFailureAndDie(void *addr, uptr size, error_t err, 65 1.4 mrg bool raw_report) { 66 1.4 mrg static int recursion_count; 67 1.4 mrg if (raw_report || recursion_count) { 68 1.4 mrg // If raw report is requested or we went into recursion just die. The 69 1.4 mrg // Report() and CHECK calls below may call munmap recursively and fail. 70 1.4 mrg RawWrite("ERROR: Failed to munmap\n"); 71 1.4 mrg Die(); 72 1.4 mrg } 73 1.4 mrg recursion_count++; 74 1.4 mrg Report( 75 1.4 mrg "ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p (error " 76 1.4 mrg "code: %d)\n", 77 1.4 mrg SanitizerToolName, size, size, addr, err); 78 1.4 mrg #if !SANITIZER_GO 79 1.4 mrg DumpProcessMap(); 80 1.4 mrg #endif 81 1.4 mrg UNREACHABLE("unable to unmmap"); 82 1.4 mrg } 83 1.4 mrg 84 1.1 mrg typedef bool UptrComparisonFunction(const uptr &a, const uptr &b); 85 1.1 mrg typedef bool U32ComparisonFunction(const u32 &a, const u32 &b); 86 1.1 mrg 87 1.1 mrg const char *StripPathPrefix(const char *filepath, 88 1.1 mrg const char *strip_path_prefix) { 89 1.1 mrg if (!filepath) return nullptr; 90 1.1 mrg if (!strip_path_prefix) return filepath; 91 1.1 mrg const char *res = filepath; 92 1.1 mrg if (const char *pos = internal_strstr(filepath, strip_path_prefix)) 93 1.1 mrg res = pos + internal_strlen(strip_path_prefix); 94 1.1 mrg if (res[0] == '.' && res[1] == '/') 95 1.1 mrg res += 2; 96 1.1 mrg return res; 97 1.1 mrg } 98 1.1 mrg 99 1.1 mrg const char *StripModuleName(const char *module) { 100 1.1 mrg if (!module) 101 1.1 mrg return nullptr; 102 1.1 mrg if (SANITIZER_WINDOWS) { 103 1.1 mrg // On Windows, both slash and backslash are possible. 104 1.1 mrg // Pick the one that goes last. 105 1.1 mrg if (const char *bslash_pos = internal_strrchr(module, '\\')) 106 1.1 mrg return StripModuleName(bslash_pos + 1); 107 1.1 mrg } 108 1.1 mrg if (const char *slash_pos = internal_strrchr(module, '/')) { 109 1.1 mrg return slash_pos + 1; 110 1.1 mrg } 111 1.1 mrg return module; 112 1.1 mrg } 113 1.1 mrg 114 1.1 mrg void ReportErrorSummary(const char *error_message, const char *alt_tool_name) { 115 1.1 mrg if (!common_flags()->print_summary) 116 1.1 mrg return; 117 1.3 mrg InternalScopedString buff; 118 1.4 mrg buff.AppendF("SUMMARY: %s: %s", 119 1.4 mrg alt_tool_name ? alt_tool_name : SanitizerToolName, 120 1.4 mrg error_message); 121 1.1 mrg __sanitizer_report_error_summary(buff.data()); 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg // Removes the ANSI escape sequences from the input string (in-place). 125 1.1 mrg void RemoveANSIEscapeSequencesFromString(char *str) { 126 1.1 mrg if (!str) 127 1.1 mrg return; 128 1.1 mrg 129 1.1 mrg // We are going to remove the escape sequences in place. 130 1.1 mrg char *s = str; 131 1.1 mrg char *z = str; 132 1.1 mrg while (*s != '\0') { 133 1.1 mrg CHECK_GE(s, z); 134 1.1 mrg // Skip over ANSI escape sequences with pointer 's'. 135 1.1 mrg if (*s == '\033' && *(s + 1) == '[') { 136 1.1 mrg s = internal_strchrnul(s, 'm'); 137 1.1 mrg if (*s == '\0') { 138 1.1 mrg break; 139 1.1 mrg } 140 1.1 mrg s++; 141 1.1 mrg continue; 142 1.1 mrg } 143 1.1 mrg // 's' now points at a character we want to keep. Copy over the buffer 144 1.1 mrg // content if the escape sequence has been perviously skipped andadvance 145 1.1 mrg // both pointers. 146 1.1 mrg if (s != z) 147 1.1 mrg *z = *s; 148 1.1 mrg 149 1.1 mrg // If we have not seen an escape sequence, just advance both pointers. 150 1.1 mrg z++; 151 1.1 mrg s++; 152 1.1 mrg } 153 1.1 mrg 154 1.1 mrg // Null terminate the string. 155 1.1 mrg *z = '\0'; 156 1.1 mrg } 157 1.1 mrg 158 1.1 mrg void LoadedModule::set(const char *module_name, uptr base_address) { 159 1.1 mrg clear(); 160 1.1 mrg full_name_ = internal_strdup(module_name); 161 1.1 mrg base_address_ = base_address; 162 1.1 mrg } 163 1.1 mrg 164 1.1 mrg void LoadedModule::set(const char *module_name, uptr base_address, 165 1.1 mrg ModuleArch arch, u8 uuid[kModuleUUIDSize], 166 1.1 mrg bool instrumented) { 167 1.1 mrg set(module_name, base_address); 168 1.1 mrg arch_ = arch; 169 1.1 mrg internal_memcpy(uuid_, uuid, sizeof(uuid_)); 170 1.4 mrg uuid_size_ = kModuleUUIDSize; 171 1.1 mrg instrumented_ = instrumented; 172 1.1 mrg } 173 1.1 mrg 174 1.4 mrg void LoadedModule::setUuid(const char *uuid, uptr size) { 175 1.4 mrg if (size > kModuleUUIDSize) 176 1.4 mrg size = kModuleUUIDSize; 177 1.4 mrg internal_memcpy(uuid_, uuid, size); 178 1.4 mrg uuid_size_ = size; 179 1.4 mrg } 180 1.4 mrg 181 1.1 mrg void LoadedModule::clear() { 182 1.1 mrg InternalFree(full_name_); 183 1.1 mrg base_address_ = 0; 184 1.4 mrg max_address_ = 0; 185 1.1 mrg full_name_ = nullptr; 186 1.1 mrg arch_ = kModuleArchUnknown; 187 1.1 mrg internal_memset(uuid_, 0, kModuleUUIDSize); 188 1.1 mrg instrumented_ = false; 189 1.1 mrg while (!ranges_.empty()) { 190 1.1 mrg AddressRange *r = ranges_.front(); 191 1.1 mrg ranges_.pop_front(); 192 1.1 mrg InternalFree(r); 193 1.1 mrg } 194 1.1 mrg } 195 1.1 mrg 196 1.1 mrg void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable, 197 1.1 mrg bool writable, const char *name) { 198 1.1 mrg void *mem = InternalAlloc(sizeof(AddressRange)); 199 1.1 mrg AddressRange *r = 200 1.1 mrg new(mem) AddressRange(beg, end, executable, writable, name); 201 1.1 mrg ranges_.push_back(r); 202 1.4 mrg max_address_ = Max(max_address_, end); 203 1.1 mrg } 204 1.1 mrg 205 1.1 mrg bool LoadedModule::containsAddress(uptr address) const { 206 1.1 mrg for (const AddressRange &r : ranges()) { 207 1.1 mrg if (r.beg <= address && address < r.end) 208 1.1 mrg return true; 209 1.1 mrg } 210 1.1 mrg return false; 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg static atomic_uintptr_t g_total_mmaped; 214 1.1 mrg 215 1.1 mrg void IncreaseTotalMmap(uptr size) { 216 1.1 mrg if (!common_flags()->mmap_limit_mb) return; 217 1.1 mrg uptr total_mmaped = 218 1.1 mrg atomic_fetch_add(&g_total_mmaped, size, memory_order_relaxed) + size; 219 1.1 mrg // Since for now mmap_limit_mb is not a user-facing flag, just kill 220 1.1 mrg // a program. Use RAW_CHECK to avoid extra mmaps in reporting. 221 1.1 mrg RAW_CHECK((total_mmaped >> 20) < common_flags()->mmap_limit_mb); 222 1.1 mrg } 223 1.1 mrg 224 1.1 mrg void DecreaseTotalMmap(uptr size) { 225 1.1 mrg if (!common_flags()->mmap_limit_mb) return; 226 1.1 mrg atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed); 227 1.1 mrg } 228 1.1 mrg 229 1.1 mrg bool TemplateMatch(const char *templ, const char *str) { 230 1.1 mrg if ((!str) || str[0] == 0) 231 1.1 mrg return false; 232 1.1 mrg bool start = false; 233 1.1 mrg if (templ && templ[0] == '^') { 234 1.1 mrg start = true; 235 1.1 mrg templ++; 236 1.1 mrg } 237 1.1 mrg bool asterisk = false; 238 1.1 mrg while (templ && templ[0]) { 239 1.1 mrg if (templ[0] == '*') { 240 1.1 mrg templ++; 241 1.1 mrg start = false; 242 1.1 mrg asterisk = true; 243 1.1 mrg continue; 244 1.1 mrg } 245 1.1 mrg if (templ[0] == '$') 246 1.1 mrg return str[0] == 0 || asterisk; 247 1.1 mrg if (str[0] == 0) 248 1.1 mrg return false; 249 1.1 mrg char *tpos = (char*)internal_strchr(templ, '*'); 250 1.1 mrg char *tpos1 = (char*)internal_strchr(templ, '$'); 251 1.1 mrg if ((!tpos) || (tpos1 && tpos1 < tpos)) 252 1.1 mrg tpos = tpos1; 253 1.1 mrg if (tpos) 254 1.1 mrg tpos[0] = 0; 255 1.1 mrg const char *str0 = str; 256 1.1 mrg const char *spos = internal_strstr(str, templ); 257 1.1 mrg str = spos + internal_strlen(templ); 258 1.1 mrg templ = tpos; 259 1.1 mrg if (tpos) 260 1.1 mrg tpos[0] = tpos == tpos1 ? '$' : '*'; 261 1.1 mrg if (!spos) 262 1.1 mrg return false; 263 1.1 mrg if (start && spos != str0) 264 1.1 mrg return false; 265 1.1 mrg start = false; 266 1.1 mrg asterisk = false; 267 1.1 mrg } 268 1.1 mrg return true; 269 1.1 mrg } 270 1.1 mrg 271 1.1 mrg static char binary_name_cache_str[kMaxPathLength]; 272 1.1 mrg static char process_name_cache_str[kMaxPathLength]; 273 1.1 mrg 274 1.1 mrg const char *GetProcessName() { 275 1.1 mrg return process_name_cache_str; 276 1.1 mrg } 277 1.1 mrg 278 1.1 mrg static uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) { 279 1.1 mrg ReadLongProcessName(buf, buf_len); 280 1.1 mrg char *s = const_cast<char *>(StripModuleName(buf)); 281 1.1 mrg uptr len = internal_strlen(s); 282 1.1 mrg if (s != buf) { 283 1.1 mrg internal_memmove(buf, s, len); 284 1.1 mrg buf[len] = '\0'; 285 1.1 mrg } 286 1.1 mrg return len; 287 1.1 mrg } 288 1.1 mrg 289 1.1 mrg void UpdateProcessName() { 290 1.1 mrg ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); 291 1.1 mrg } 292 1.1 mrg 293 1.1 mrg // Call once to make sure that binary_name_cache_str is initialized 294 1.1 mrg void CacheBinaryName() { 295 1.1 mrg if (binary_name_cache_str[0] != '\0') 296 1.1 mrg return; 297 1.1 mrg ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str)); 298 1.1 mrg ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); 299 1.1 mrg } 300 1.1 mrg 301 1.1 mrg uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) { 302 1.1 mrg CacheBinaryName(); 303 1.1 mrg uptr name_len = internal_strlen(binary_name_cache_str); 304 1.1 mrg name_len = (name_len < buf_len - 1) ? name_len : buf_len - 1; 305 1.1 mrg if (buf_len == 0) 306 1.1 mrg return 0; 307 1.1 mrg internal_memcpy(buf, binary_name_cache_str, name_len); 308 1.1 mrg buf[name_len] = '\0'; 309 1.1 mrg return name_len; 310 1.1 mrg } 311 1.1 mrg 312 1.3 mrg uptr ReadBinaryDir(/*out*/ char *buf, uptr buf_len) { 313 1.3 mrg ReadBinaryNameCached(buf, buf_len); 314 1.3 mrg const char *exec_name_pos = StripModuleName(buf); 315 1.3 mrg uptr name_len = exec_name_pos - buf; 316 1.3 mrg buf[name_len] = '\0'; 317 1.3 mrg return name_len; 318 1.3 mrg } 319 1.3 mrg 320 1.3 mrg #if !SANITIZER_GO 321 1.1 mrg void PrintCmdline() { 322 1.1 mrg char **argv = GetArgv(); 323 1.1 mrg if (!argv) return; 324 1.1 mrg Printf("\nCommand: "); 325 1.1 mrg for (uptr i = 0; argv[i]; ++i) 326 1.1 mrg Printf("%s ", argv[i]); 327 1.1 mrg Printf("\n\n"); 328 1.1 mrg } 329 1.3 mrg #endif 330 1.1 mrg 331 1.1 mrg // Malloc hooks. 332 1.1 mrg static const int kMaxMallocFreeHooks = 5; 333 1.1 mrg struct MallocFreeHook { 334 1.1 mrg void (*malloc_hook)(const void *, uptr); 335 1.1 mrg void (*free_hook)(const void *); 336 1.1 mrg }; 337 1.1 mrg 338 1.1 mrg static MallocFreeHook MFHooks[kMaxMallocFreeHooks]; 339 1.1 mrg 340 1.4 mrg void RunMallocHooks(void *ptr, uptr size) { 341 1.4 mrg __sanitizer_malloc_hook(ptr, size); 342 1.1 mrg for (int i = 0; i < kMaxMallocFreeHooks; i++) { 343 1.1 mrg auto hook = MFHooks[i].malloc_hook; 344 1.4 mrg if (!hook) 345 1.4 mrg break; 346 1.1 mrg hook(ptr, size); 347 1.1 mrg } 348 1.1 mrg } 349 1.1 mrg 350 1.4 mrg void RunFreeHooks(void *ptr) { 351 1.4 mrg __sanitizer_free_hook(ptr); 352 1.1 mrg for (int i = 0; i < kMaxMallocFreeHooks; i++) { 353 1.1 mrg auto hook = MFHooks[i].free_hook; 354 1.4 mrg if (!hook) 355 1.4 mrg break; 356 1.1 mrg hook(ptr); 357 1.1 mrg } 358 1.1 mrg } 359 1.1 mrg 360 1.1 mrg static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr), 361 1.1 mrg void (*free_hook)(const void *)) { 362 1.1 mrg if (!malloc_hook || !free_hook) return 0; 363 1.1 mrg for (int i = 0; i < kMaxMallocFreeHooks; i++) { 364 1.1 mrg if (MFHooks[i].malloc_hook == nullptr) { 365 1.1 mrg MFHooks[i].malloc_hook = malloc_hook; 366 1.1 mrg MFHooks[i].free_hook = free_hook; 367 1.1 mrg return i + 1; 368 1.1 mrg } 369 1.1 mrg } 370 1.1 mrg return 0; 371 1.1 mrg } 372 1.1 mrg 373 1.3 mrg void internal_sleep(unsigned seconds) { 374 1.3 mrg internal_usleep((u64)seconds * 1000 * 1000); 375 1.3 mrg } 376 1.3 mrg void SleepForSeconds(unsigned seconds) { 377 1.3 mrg internal_usleep((u64)seconds * 1000 * 1000); 378 1.3 mrg } 379 1.3 mrg void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); } 380 1.3 mrg 381 1.4 mrg void WaitForDebugger(unsigned seconds, const char *label) { 382 1.4 mrg if (seconds) { 383 1.4 mrg Report("Sleeping for %u second(s) %s\n", seconds, label); 384 1.4 mrg SleepForSeconds(seconds); 385 1.4 mrg } 386 1.4 mrg } 387 1.4 mrg 388 1.1 mrg } // namespace __sanitizer 389 1.1 mrg 390 1.1 mrg using namespace __sanitizer; 391 1.1 mrg 392 1.1 mrg extern "C" { 393 1.1 mrg SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary, 394 1.1 mrg const char *error_summary) { 395 1.1 mrg Printf("%s\n", error_summary); 396 1.1 mrg } 397 1.1 mrg 398 1.1 mrg SANITIZER_INTERFACE_ATTRIBUTE 399 1.1 mrg int __sanitizer_acquire_crash_state() { 400 1.1 mrg static atomic_uint8_t in_crash_state = {}; 401 1.1 mrg return !atomic_exchange(&in_crash_state, 1, memory_order_relaxed); 402 1.1 mrg } 403 1.1 mrg 404 1.1 mrg SANITIZER_INTERFACE_ATTRIBUTE 405 1.1 mrg int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *, 406 1.1 mrg uptr), 407 1.1 mrg void (*free_hook)(const void *)) { 408 1.1 mrg return InstallMallocFreeHooks(malloc_hook, free_hook); 409 1.1 mrg } 410 1.4 mrg 411 1.4 mrg // Provide default (no-op) implementation of malloc hooks. 412 1.4 mrg SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, void *ptr, 413 1.4 mrg uptr size) { 414 1.4 mrg (void)ptr; 415 1.4 mrg (void)size; 416 1.4 mrg } 417 1.4 mrg 418 1.4 mrg SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) { 419 1.4 mrg (void)ptr; 420 1.4 mrg } 421 1.4 mrg 422 1.1 mrg } // extern "C" 423