1 //===-- sanitizer_libignore.cc --------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 8 #include "sanitizer_platform.h" 9 10 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || SANITIZER_NETBSD 11 12 #include "sanitizer_libignore.h" 13 #include "sanitizer_flags.h" 14 #include "sanitizer_posix.h" 15 #include "sanitizer_procmaps.h" 16 17 namespace __sanitizer { 18 19 LibIgnore::LibIgnore(LinkerInitialized) { 20 } 21 22 void LibIgnore::AddIgnoredLibrary(const char *name_templ) { 23 BlockingMutexLock lock(&mutex_); 24 if (count_ >= kMaxLibs) { 25 Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName, 26 kMaxLibs); 27 Die(); 28 } 29 Lib *lib = &libs_[count_++]; 30 lib->templ = internal_strdup(name_templ); 31 lib->name = nullptr; 32 lib->real_name = nullptr; 33 lib->loaded = false; 34 } 35 36 void LibIgnore::OnLibraryLoaded(const char *name) { 37 BlockingMutexLock lock(&mutex_); 38 // Try to match suppressions with symlink target. 39 InternalScopedString buf(kMaxPathLength); 40 if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && 41 buf[0]) { 42 for (uptr i = 0; i < count_; i++) { 43 Lib *lib = &libs_[i]; 44 if (!lib->loaded && (!lib->real_name) && 45 TemplateMatch(lib->templ, name)) 46 lib->real_name = internal_strdup(buf.data()); 47 } 48 } 49 50 // Scan suppressions list and find newly loaded and unloaded libraries. 51 ListOfModules modules; 52 modules.init(); 53 for (uptr i = 0; i < count_; i++) { 54 Lib *lib = &libs_[i]; 55 bool loaded = false; 56 for (const auto &mod : modules) { 57 for (const auto &range : mod.ranges()) { 58 if (!range.executable) 59 continue; 60 if (!TemplateMatch(lib->templ, mod.full_name()) && 61 !(lib->real_name && 62 internal_strcmp(lib->real_name, mod.full_name()) == 0)) 63 continue; 64 if (loaded) { 65 Report("%s: called_from_lib suppression '%s' is matched against" 66 " 2 libraries: '%s' and '%s'\n", 67 SanitizerToolName, lib->templ, lib->name, mod.full_name()); 68 Die(); 69 } 70 loaded = true; 71 if (lib->loaded) 72 continue; 73 VReport(1, 74 "Matched called_from_lib suppression '%s' against library" 75 " '%s'\n", 76 lib->templ, mod.full_name()); 77 lib->loaded = true; 78 lib->name = internal_strdup(mod.full_name()); 79 const uptr idx = 80 atomic_load(&ignored_ranges_count_, memory_order_relaxed); 81 CHECK_LT(idx, kMaxLibs); 82 ignored_code_ranges_[idx].begin = range.beg; 83 ignored_code_ranges_[idx].end = range.end; 84 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release); 85 break; 86 } 87 } 88 if (lib->loaded && !loaded) { 89 Report("%s: library '%s' that was matched against called_from_lib" 90 " suppression '%s' is unloaded\n", 91 SanitizerToolName, lib->name, lib->templ); 92 Die(); 93 } 94 } 95 96 // Track instrumented ranges. 97 if (track_instrumented_libs_) { 98 for (const auto &mod : modules) { 99 if (!mod.instrumented()) 100 continue; 101 for (const auto &range : mod.ranges()) { 102 if (!range.executable) 103 continue; 104 if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1)) 105 continue; 106 VReport(1, "Adding instrumented range %p-%p from library '%s'\n", 107 range.beg, range.end, mod.full_name()); 108 const uptr idx = 109 atomic_load(&instrumented_ranges_count_, memory_order_relaxed); 110 CHECK_LT(idx, kMaxLibs); 111 instrumented_code_ranges_[idx].begin = range.beg; 112 instrumented_code_ranges_[idx].end = range.end; 113 atomic_store(&instrumented_ranges_count_, idx + 1, 114 memory_order_release); 115 } 116 } 117 } 118 } 119 120 void LibIgnore::OnLibraryUnloaded() { 121 OnLibraryLoaded(nullptr); 122 } 123 124 } // namespace __sanitizer 125 126 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || 127 // SANITIZER_NETBSD 128