168d75effSDimitry Andric //===-- sanitizer_libignore.cpp -------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric 968d75effSDimitry Andric #include "sanitizer_platform.h" 1068d75effSDimitry Andric 1181ad6265SDimitry Andric #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \ 12e8d8bef9SDimitry Andric SANITIZER_NETBSD 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "sanitizer_libignore.h" 1568d75effSDimitry Andric #include "sanitizer_flags.h" 1668d75effSDimitry Andric #include "sanitizer_posix.h" 1768d75effSDimitry Andric #include "sanitizer_procmaps.h" 1868d75effSDimitry Andric 1968d75effSDimitry Andric namespace __sanitizer { 2068d75effSDimitry Andric 2168d75effSDimitry Andric LibIgnore::LibIgnore(LinkerInitialized) { 2268d75effSDimitry Andric } 2368d75effSDimitry Andric 2468d75effSDimitry Andric void LibIgnore::AddIgnoredLibrary(const char *name_templ) { 25349cc55cSDimitry Andric Lock lock(&mutex_); 2668d75effSDimitry Andric if (count_ >= kMaxLibs) { 27349cc55cSDimitry Andric Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName, 2868d75effSDimitry Andric kMaxLibs); 2968d75effSDimitry Andric Die(); 3068d75effSDimitry Andric } 3168d75effSDimitry Andric Lib *lib = &libs_[count_++]; 3268d75effSDimitry Andric lib->templ = internal_strdup(name_templ); 3368d75effSDimitry Andric lib->name = nullptr; 3468d75effSDimitry Andric lib->real_name = nullptr; 3568d75effSDimitry Andric lib->loaded = false; 3668d75effSDimitry Andric } 3768d75effSDimitry Andric 3868d75effSDimitry Andric void LibIgnore::OnLibraryLoaded(const char *name) { 39349cc55cSDimitry Andric Lock lock(&mutex_); 4068d75effSDimitry Andric // Try to match suppressions with symlink target. 41fe6060f1SDimitry Andric InternalMmapVector<char> buf(kMaxPathLength); 4268d75effSDimitry Andric if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && 4368d75effSDimitry Andric buf[0]) { 4468d75effSDimitry Andric for (uptr i = 0; i < count_; i++) { 4568d75effSDimitry Andric Lib *lib = &libs_[i]; 4668d75effSDimitry Andric if (!lib->loaded && (!lib->real_name) && 4768d75effSDimitry Andric TemplateMatch(lib->templ, name)) 4868d75effSDimitry Andric lib->real_name = internal_strdup(buf.data()); 4968d75effSDimitry Andric } 5068d75effSDimitry Andric } 5168d75effSDimitry Andric 5268d75effSDimitry Andric // Scan suppressions list and find newly loaded and unloaded libraries. 5368d75effSDimitry Andric ListOfModules modules; 5468d75effSDimitry Andric modules.init(); 5568d75effSDimitry Andric for (uptr i = 0; i < count_; i++) { 5668d75effSDimitry Andric Lib *lib = &libs_[i]; 5768d75effSDimitry Andric bool loaded = false; 5868d75effSDimitry Andric for (const auto &mod : modules) { 5968d75effSDimitry Andric for (const auto &range : mod.ranges()) { 6068d75effSDimitry Andric if (!range.executable) 6168d75effSDimitry Andric continue; 6268d75effSDimitry Andric if (!TemplateMatch(lib->templ, mod.full_name()) && 6368d75effSDimitry Andric !(lib->real_name && 6468d75effSDimitry Andric internal_strcmp(lib->real_name, mod.full_name()) == 0)) 6568d75effSDimitry Andric continue; 6668d75effSDimitry Andric if (loaded) { 6768d75effSDimitry Andric Report("%s: called_from_lib suppression '%s' is matched against" 6868d75effSDimitry Andric " 2 libraries: '%s' and '%s'\n", 6968d75effSDimitry Andric SanitizerToolName, lib->templ, lib->name, mod.full_name()); 7068d75effSDimitry Andric Die(); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric loaded = true; 7368d75effSDimitry Andric if (lib->loaded) 7468d75effSDimitry Andric continue; 7568d75effSDimitry Andric VReport(1, 7668d75effSDimitry Andric "Matched called_from_lib suppression '%s' against library" 7768d75effSDimitry Andric " '%s'\n", 7868d75effSDimitry Andric lib->templ, mod.full_name()); 7968d75effSDimitry Andric lib->loaded = true; 8068d75effSDimitry Andric lib->name = internal_strdup(mod.full_name()); 8168d75effSDimitry Andric const uptr idx = 8268d75effSDimitry Andric atomic_load(&ignored_ranges_count_, memory_order_relaxed); 8368d75effSDimitry Andric CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_)); 8468d75effSDimitry Andric ignored_code_ranges_[idx].begin = range.beg; 8568d75effSDimitry Andric ignored_code_ranges_[idx].end = range.end; 8668d75effSDimitry Andric atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release); 8768d75effSDimitry Andric break; 8868d75effSDimitry Andric } 8968d75effSDimitry Andric } 9068d75effSDimitry Andric if (lib->loaded && !loaded) { 9168d75effSDimitry Andric Report("%s: library '%s' that was matched against called_from_lib" 9268d75effSDimitry Andric " suppression '%s' is unloaded\n", 9368d75effSDimitry Andric SanitizerToolName, lib->name, lib->templ); 9468d75effSDimitry Andric Die(); 9568d75effSDimitry Andric } 9668d75effSDimitry Andric } 9768d75effSDimitry Andric 9868d75effSDimitry Andric // Track instrumented ranges. 9968d75effSDimitry Andric if (track_instrumented_libs_) { 10068d75effSDimitry Andric for (const auto &mod : modules) { 10168d75effSDimitry Andric if (!mod.instrumented()) 10268d75effSDimitry Andric continue; 10368d75effSDimitry Andric for (const auto &range : mod.ranges()) { 10468d75effSDimitry Andric if (!range.executable) 10568d75effSDimitry Andric continue; 10668d75effSDimitry Andric if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1)) 10768d75effSDimitry Andric continue; 108*0fca6ea1SDimitry Andric VReport(1, "Adding instrumented range %p-%p from library '%s'\n", 109*0fca6ea1SDimitry Andric (void *)range.beg, (void *)range.end, mod.full_name()); 11068d75effSDimitry Andric const uptr idx = 11168d75effSDimitry Andric atomic_load(&instrumented_ranges_count_, memory_order_relaxed); 11268d75effSDimitry Andric CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_)); 11368d75effSDimitry Andric instrumented_code_ranges_[idx].begin = range.beg; 11468d75effSDimitry Andric instrumented_code_ranges_[idx].end = range.end; 11568d75effSDimitry Andric atomic_store(&instrumented_ranges_count_, idx + 1, 11668d75effSDimitry Andric memory_order_release); 11768d75effSDimitry Andric } 11868d75effSDimitry Andric } 11968d75effSDimitry Andric } 12068d75effSDimitry Andric } 12168d75effSDimitry Andric 12268d75effSDimitry Andric void LibIgnore::OnLibraryUnloaded() { 12368d75effSDimitry Andric OnLibraryLoaded(nullptr); 12468d75effSDimitry Andric } 12568d75effSDimitry Andric 12668d75effSDimitry Andric } // namespace __sanitizer 12768d75effSDimitry Andric 12881ad6265SDimitry Andric #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || 12968d75effSDimitry Andric // SANITIZER_NETBSD 130