13cab2bb3Spatrick //===-- sanitizer_libignore.cpp -------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick
93cab2bb3Spatrick #include "sanitizer_platform.h"
103cab2bb3Spatrick
11*810390e3Srobert #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
12d89ec533Spatrick SANITIZER_NETBSD
133cab2bb3Spatrick
143cab2bb3Spatrick #include "sanitizer_libignore.h"
153cab2bb3Spatrick #include "sanitizer_flags.h"
163cab2bb3Spatrick #include "sanitizer_posix.h"
173cab2bb3Spatrick #include "sanitizer_procmaps.h"
183cab2bb3Spatrick
193cab2bb3Spatrick namespace __sanitizer {
203cab2bb3Spatrick
LibIgnore(LinkerInitialized)213cab2bb3Spatrick LibIgnore::LibIgnore(LinkerInitialized) {
223cab2bb3Spatrick }
233cab2bb3Spatrick
AddIgnoredLibrary(const char * name_templ)243cab2bb3Spatrick void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
25*810390e3Srobert Lock lock(&mutex_);
263cab2bb3Spatrick if (count_ >= kMaxLibs) {
27*810390e3Srobert Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName,
283cab2bb3Spatrick kMaxLibs);
293cab2bb3Spatrick Die();
303cab2bb3Spatrick }
313cab2bb3Spatrick Lib *lib = &libs_[count_++];
323cab2bb3Spatrick lib->templ = internal_strdup(name_templ);
333cab2bb3Spatrick lib->name = nullptr;
343cab2bb3Spatrick lib->real_name = nullptr;
353cab2bb3Spatrick lib->loaded = false;
363cab2bb3Spatrick }
373cab2bb3Spatrick
OnLibraryLoaded(const char * name)383cab2bb3Spatrick void LibIgnore::OnLibraryLoaded(const char *name) {
39*810390e3Srobert Lock lock(&mutex_);
403cab2bb3Spatrick // Try to match suppressions with symlink target.
41d89ec533Spatrick InternalMmapVector<char> buf(kMaxPathLength);
423cab2bb3Spatrick if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
433cab2bb3Spatrick buf[0]) {
443cab2bb3Spatrick for (uptr i = 0; i < count_; i++) {
453cab2bb3Spatrick Lib *lib = &libs_[i];
463cab2bb3Spatrick if (!lib->loaded && (!lib->real_name) &&
473cab2bb3Spatrick TemplateMatch(lib->templ, name))
483cab2bb3Spatrick lib->real_name = internal_strdup(buf.data());
493cab2bb3Spatrick }
503cab2bb3Spatrick }
513cab2bb3Spatrick
523cab2bb3Spatrick // Scan suppressions list and find newly loaded and unloaded libraries.
533cab2bb3Spatrick ListOfModules modules;
543cab2bb3Spatrick modules.init();
553cab2bb3Spatrick for (uptr i = 0; i < count_; i++) {
563cab2bb3Spatrick Lib *lib = &libs_[i];
573cab2bb3Spatrick bool loaded = false;
583cab2bb3Spatrick for (const auto &mod : modules) {
593cab2bb3Spatrick for (const auto &range : mod.ranges()) {
603cab2bb3Spatrick if (!range.executable)
613cab2bb3Spatrick continue;
623cab2bb3Spatrick if (!TemplateMatch(lib->templ, mod.full_name()) &&
633cab2bb3Spatrick !(lib->real_name &&
643cab2bb3Spatrick internal_strcmp(lib->real_name, mod.full_name()) == 0))
653cab2bb3Spatrick continue;
663cab2bb3Spatrick if (loaded) {
673cab2bb3Spatrick Report("%s: called_from_lib suppression '%s' is matched against"
683cab2bb3Spatrick " 2 libraries: '%s' and '%s'\n",
693cab2bb3Spatrick SanitizerToolName, lib->templ, lib->name, mod.full_name());
703cab2bb3Spatrick Die();
713cab2bb3Spatrick }
723cab2bb3Spatrick loaded = true;
733cab2bb3Spatrick if (lib->loaded)
743cab2bb3Spatrick continue;
753cab2bb3Spatrick VReport(1,
763cab2bb3Spatrick "Matched called_from_lib suppression '%s' against library"
773cab2bb3Spatrick " '%s'\n",
783cab2bb3Spatrick lib->templ, mod.full_name());
793cab2bb3Spatrick lib->loaded = true;
803cab2bb3Spatrick lib->name = internal_strdup(mod.full_name());
813cab2bb3Spatrick const uptr idx =
823cab2bb3Spatrick atomic_load(&ignored_ranges_count_, memory_order_relaxed);
833cab2bb3Spatrick CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
843cab2bb3Spatrick ignored_code_ranges_[idx].begin = range.beg;
853cab2bb3Spatrick ignored_code_ranges_[idx].end = range.end;
863cab2bb3Spatrick atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
873cab2bb3Spatrick break;
883cab2bb3Spatrick }
893cab2bb3Spatrick }
903cab2bb3Spatrick if (lib->loaded && !loaded) {
913cab2bb3Spatrick Report("%s: library '%s' that was matched against called_from_lib"
923cab2bb3Spatrick " suppression '%s' is unloaded\n",
933cab2bb3Spatrick SanitizerToolName, lib->name, lib->templ);
943cab2bb3Spatrick Die();
953cab2bb3Spatrick }
963cab2bb3Spatrick }
973cab2bb3Spatrick
983cab2bb3Spatrick // Track instrumented ranges.
993cab2bb3Spatrick if (track_instrumented_libs_) {
1003cab2bb3Spatrick for (const auto &mod : modules) {
1013cab2bb3Spatrick if (!mod.instrumented())
1023cab2bb3Spatrick continue;
1033cab2bb3Spatrick for (const auto &range : mod.ranges()) {
1043cab2bb3Spatrick if (!range.executable)
1053cab2bb3Spatrick continue;
1063cab2bb3Spatrick if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
1073cab2bb3Spatrick continue;
108*810390e3Srobert VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
1093cab2bb3Spatrick range.beg, range.end, mod.full_name());
1103cab2bb3Spatrick const uptr idx =
1113cab2bb3Spatrick atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
1123cab2bb3Spatrick CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
1133cab2bb3Spatrick instrumented_code_ranges_[idx].begin = range.beg;
1143cab2bb3Spatrick instrumented_code_ranges_[idx].end = range.end;
1153cab2bb3Spatrick atomic_store(&instrumented_ranges_count_, idx + 1,
1163cab2bb3Spatrick memory_order_release);
1173cab2bb3Spatrick }
1183cab2bb3Spatrick }
1193cab2bb3Spatrick }
1203cab2bb3Spatrick }
1213cab2bb3Spatrick
OnLibraryUnloaded()1223cab2bb3Spatrick void LibIgnore::OnLibraryUnloaded() {
1233cab2bb3Spatrick OnLibraryLoaded(nullptr);
1243cab2bb3Spatrick }
1253cab2bb3Spatrick
1263cab2bb3Spatrick } // namespace __sanitizer
1273cab2bb3Spatrick
128*810390e3Srobert #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE ||
1293cab2bb3Spatrick // SANITIZER_NETBSD
130