1 //===-- sanitizer_libignore.cpp -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "sanitizer_platform.h" 10 11 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \ 12 SANITIZER_NETBSD 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 Lock lock(&mutex_); 26 if (count_ >= kMaxLibs) { 27 Report("%s: too many ignored libraries (max: %zu)\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->range_id = kInvalidCodeRangeId; 36 } 37 38 void LibIgnore::OnLibraryLoaded(const char *name) { 39 Lock lock(&mutex_); 40 // Try to match suppressions with symlink target. 41 InternalMmapVector<char> 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 ListOfModules modules; 54 modules.init(); 55 for (uptr i = 0; i < count_; i++) { 56 Lib *lib = &libs_[i]; 57 bool loaded = false; 58 for (const auto &mod : modules) { 59 for (const auto &range : mod.ranges()) { 60 if (!range.executable) 61 continue; 62 if (!TemplateMatch(lib->templ, mod.full_name()) && 63 !(lib->real_name && 64 internal_strcmp(lib->real_name, mod.full_name()) == 0)) 65 continue; 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, mod.full_name()); 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, mod.full_name()); 79 lib->name = internal_strdup(mod.full_name()); 80 const uptr idx = 81 atomic_load(&ignored_ranges_count_, memory_order_relaxed); 82 CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_)); 83 ignored_code_ranges_[idx].OnLoad(range.beg, range.end); 84 // Record the index of the ignored range. 85 lib->range_id = idx; 86 atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release); 87 break; 88 } 89 } 90 if (lib->loaded() && !loaded) { 91 VReport(1, 92 "%s: library '%s' that was matched against called_from_lib" 93 " suppression '%s' is unloaded\n", 94 SanitizerToolName, lib->name, lib->templ); 95 // The library is unloaded so mark the ignored code range as unloaded. 96 ignored_code_ranges_[lib->range_id].OnUnload(); 97 lib->range_id = kInvalidCodeRangeId; 98 } 99 } 100 101 // Track instrumented ranges. 102 if (track_instrumented_libs_) { 103 for (const auto &mod : modules) { 104 if (!mod.instrumented()) 105 continue; 106 for (const auto &range : mod.ranges()) { 107 if (!range.executable) 108 continue; 109 if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1)) 110 continue; 111 VReport(1, "Adding instrumented range %p-%p from library '%s'\n", 112 (void *)range.beg, (void *)range.end, mod.full_name()); 113 const uptr idx = 114 atomic_load(&instrumented_ranges_count_, memory_order_relaxed); 115 CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_)); 116 instrumented_code_ranges_[idx].OnLoad(range.beg, range.end); 117 atomic_store(&instrumented_ranges_count_, idx + 1, 118 memory_order_release); 119 } 120 } 121 } 122 } 123 124 void LibIgnore::OnLibraryUnloaded() { 125 OnLibraryLoaded(nullptr); 126 } 127 128 } // namespace __sanitizer 129 130 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || 131 // SANITIZER_NETBSD 132