1353944Sdim//===-- sanitizer_libignore.cpp -------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim 9353944Sdim#include "sanitizer_platform.h" 10353944Sdim 11353944Sdim#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \ 12353944Sdim SANITIZER_NETBSD || SANITIZER_OPENBSD 13353944Sdim 14353944Sdim#include "sanitizer_libignore.h" 15353944Sdim#include "sanitizer_flags.h" 16353944Sdim#include "sanitizer_posix.h" 17353944Sdim#include "sanitizer_procmaps.h" 18353944Sdim 19353944Sdimnamespace __sanitizer { 20353944Sdim 21353944SdimLibIgnore::LibIgnore(LinkerInitialized) { 22353944Sdim} 23353944Sdim 24353944Sdimvoid LibIgnore::AddIgnoredLibrary(const char *name_templ) { 25353944Sdim BlockingMutexLock lock(&mutex_); 26353944Sdim if (count_ >= kMaxLibs) { 27353944Sdim Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName, 28353944Sdim kMaxLibs); 29353944Sdim Die(); 30353944Sdim } 31353944Sdim Lib *lib = &libs_[count_++]; 32353944Sdim lib->templ = internal_strdup(name_templ); 33353944Sdim lib->name = nullptr; 34353944Sdim lib->real_name = nullptr; 35353944Sdim lib->loaded = false; 36353944Sdim} 37353944Sdim 38353944Sdimvoid LibIgnore::OnLibraryLoaded(const char *name) { 39353944Sdim BlockingMutexLock lock(&mutex_); 40353944Sdim // Try to match suppressions with symlink target. 41353944Sdim InternalScopedString buf(kMaxPathLength); 42353944Sdim if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && 43353944Sdim buf[0]) { 44353944Sdim for (uptr i = 0; i < count_; i++) { 45353944Sdim Lib *lib = &libs_[i]; 46353944Sdim if (!lib->loaded && (!lib->real_name) && 47353944Sdim TemplateMatch(lib->templ, name)) 48353944Sdim lib->real_name = internal_strdup(buf.data()); 49353944Sdim } 50353944Sdim } 51353944Sdim 52353944Sdim // Scan suppressions list and find newly loaded and unloaded libraries. 53353944Sdim ListOfModules modules; 54353944Sdim modules.init(); 55353944Sdim for (uptr i = 0; i < count_; i++) { 56353944Sdim Lib *lib = &libs_[i]; 57353944Sdim bool loaded = false; 58353944Sdim for (const auto &mod : modules) { 59353944Sdim for (const auto &range : mod.ranges()) { 60353944Sdim if (!range.executable) 61353944Sdim continue; 62353944Sdim if (!TemplateMatch(lib->templ, mod.full_name()) && 63353944Sdim !(lib->real_name && 64353944Sdim internal_strcmp(lib->real_name, mod.full_name()) == 0)) 65353944Sdim continue; 66353944Sdim if (loaded) { 67353944Sdim Report("%s: called_from_lib suppression '%s' is matched against" 68353944Sdim " 2 libraries: '%s' and '%s'\n", 69353944Sdim SanitizerToolName, lib->templ, lib->name, mod.full_name()); 70353944Sdim Die(); 71353944Sdim } 72353944Sdim loaded = true; 73353944Sdim if (lib->loaded) 74353944Sdim continue; 75353944Sdim VReport(1, 76353944Sdim "Matched called_from_lib suppression '%s' against library" 77353944Sdim " '%s'\n", 78353944Sdim lib->templ, mod.full_name()); 79353944Sdim lib->loaded = true; 80353944Sdim lib->name = internal_strdup(mod.full_name()); 81353944Sdim const uptr idx = 82353944Sdim atomic_load(&ignored_ranges_count_, memory_order_relaxed); 83353944Sdim CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_)); 84353944Sdim ignored_code_ranges_[idx].begin = range.beg; 85353944Sdim ignored_code_ranges_[idx].end = range.end; 86353944Sdim atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release); 87353944Sdim break; 88353944Sdim } 89353944Sdim } 90353944Sdim if (lib->loaded && !loaded) { 91353944Sdim Report("%s: library '%s' that was matched against called_from_lib" 92353944Sdim " suppression '%s' is unloaded\n", 93353944Sdim SanitizerToolName, lib->name, lib->templ); 94353944Sdim Die(); 95353944Sdim } 96353944Sdim } 97353944Sdim 98353944Sdim // Track instrumented ranges. 99353944Sdim if (track_instrumented_libs_) { 100353944Sdim for (const auto &mod : modules) { 101353944Sdim if (!mod.instrumented()) 102353944Sdim continue; 103353944Sdim for (const auto &range : mod.ranges()) { 104353944Sdim if (!range.executable) 105353944Sdim continue; 106353944Sdim if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1)) 107353944Sdim continue; 108353944Sdim VReport(1, "Adding instrumented range %p-%p from library '%s'\n", 109353944Sdim range.beg, range.end, mod.full_name()); 110353944Sdim const uptr idx = 111353944Sdim atomic_load(&instrumented_ranges_count_, memory_order_relaxed); 112353944Sdim CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_)); 113353944Sdim instrumented_code_ranges_[idx].begin = range.beg; 114353944Sdim instrumented_code_ranges_[idx].end = range.end; 115353944Sdim atomic_store(&instrumented_ranges_count_, idx + 1, 116353944Sdim memory_order_release); 117353944Sdim } 118353944Sdim } 119353944Sdim } 120353944Sdim} 121353944Sdim 122353944Sdimvoid LibIgnore::OnLibraryUnloaded() { 123353944Sdim OnLibraryLoaded(nullptr); 124353944Sdim} 125353944Sdim 126353944Sdim} // namespace __sanitizer 127353944Sdim 128353944Sdim#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || 129353944Sdim // SANITIZER_NETBSD 130