xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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