1 //===-- sanitizer_libignore.cc --------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "sanitizer_platform.h" 11 12 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC 13 14 #include "sanitizer_libignore.h" 15 #include "sanitizer_flags.h" 16 #include "sanitizer_posix.h" 17 #include "sanitizer_procmaps.h" 18 19 namespace __sanitizer { 20 21 LibIgnore::LibIgnore(LinkerInitialized) { 22 } 23 24 void LibIgnore::AddIgnoredLibrary(const char *name_templ) { 25 BlockingMutexLock lock(&mutex_); 26 if (count_ >= kMaxLibs) { 27 Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName, 28 kMaxLibs); 29 Die(); 30 } 31 Lib *lib = &libs_[count_++]; 32 lib->templ = internal_strdup(name_templ); 33 lib->name = nullptr; 34 lib->real_name = nullptr; 35 lib->loaded = false; 36 } 37 38 void LibIgnore::OnLibraryLoaded(const char *name) { 39 BlockingMutexLock lock(&mutex_); 40 // Try to match suppressions with symlink target. 41 InternalScopedString buf(kMaxPathLength); 42 if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && 43 buf[0]) { 44 for (uptr i = 0; i < count_; i++) { 45 Lib *lib = &libs_[i]; 46 if (!lib->loaded && (!lib->real_name) && 47 TemplateMatch(lib->templ, name)) 48 lib->real_name = internal_strdup(buf.data()); 49 } 50 } 51 52 // Scan suppressions list and find newly loaded and unloaded libraries. 53 MemoryMappingLayout proc_maps(/*cache_enabled*/false); 54 InternalScopedString module(kMaxPathLength); 55 for (uptr i = 0; i < count_; i++) { 56 Lib *lib = &libs_[i]; 57 bool loaded = false; 58 proc_maps.Reset(); 59 uptr b, e, off, prot; 60 while (proc_maps.Next(&b, &e, &off, module.data(), module.size(), &prot)) { 61 if ((prot & MemoryMappingLayout::kProtectionExecute) == 0) 62 continue; 63 if (TemplateMatch(lib->templ, module.data()) || 64 (lib->real_name && 65 internal_strcmp(lib->real_name, module.data()) == 0)) { 66 if (loaded) { 67 Report("%s: called_from_lib suppression '%s' is matched against" 68 " 2 libraries: '%s' and '%s'\n", 69 SanitizerToolName, lib->templ, lib->name, module.data()); 70 Die(); 71 } 72 loaded = true; 73 if (lib->loaded) 74 continue; 75 VReport(1, 76 "Matched called_from_lib suppression '%s' against library" 77 " '%s'\n", 78 lib->templ, module.data()); 79 lib->loaded = true; 80 lib->name = internal_strdup(module.data()); 81 const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed); 82 code_ranges_[idx].begin = b; 83 code_ranges_[idx].end = e; 84 atomic_store(&loaded_count_, idx + 1, memory_order_release); 85 } 86 } 87 if (lib->loaded && !loaded) { 88 Report("%s: library '%s' that was matched against called_from_lib" 89 " suppression '%s' is unloaded\n", 90 SanitizerToolName, lib->name, lib->templ); 91 Die(); 92 } 93 } 94 } 95 96 void LibIgnore::OnLibraryUnloaded() { 97 OnLibraryLoaded(nullptr); 98 } 99 100 } // namespace __sanitizer 101 102 #endif // #if SANITIZER_FREEBSD || SANITIZER_LINUX 103