132 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "sanitizer_platform.h"10 11#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \12 SANITIZER_NETBSD13 14#include "sanitizer_libignore.h"15#include "sanitizer_flags.h"16#include "sanitizer_posix.h"17#include "sanitizer_procmaps.h"18 19namespace __sanitizer {20 21LibIgnore::LibIgnore(LinkerInitialized) {22}23 24void 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 38void 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 124void LibIgnore::OnLibraryUnloaded() {125 OnLibraryLoaded(nullptr);126}127 128} // namespace __sanitizer129 130#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE ||131 // SANITIZER_NETBSD132