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