Home | History | Annotate | Line # | Download | only in sanitizer_common
      1 //===-- sanitizer_libignore.cc --------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "sanitizer_platform.h"
     11 
     12 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC || \
     13     SANITIZER_NETBSD || SANITIZER_OPENBSD
     14 
     15 #include "sanitizer_libignore.h"
     16 #include "sanitizer_flags.h"
     17 #include "sanitizer_posix.h"
     18 #include "sanitizer_procmaps.h"
     19 
     20 namespace __sanitizer {
     21 
     22 LibIgnore::LibIgnore(LinkerInitialized) {
     23 }
     24 
     25 void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
     26   BlockingMutexLock lock(&mutex_);
     27   if (count_ >= kMaxLibs) {
     28     Report("%s: too many ignored libraries (max: %d)\n", SanitizerToolName,
     29            kMaxLibs);
     30     Die();
     31   }
     32   Lib *lib = &libs_[count_++];
     33   lib->templ = internal_strdup(name_templ);
     34   lib->name = nullptr;
     35   lib->real_name = nullptr;
     36   lib->loaded = false;
     37 }
     38 
     39 void LibIgnore::OnLibraryLoaded(const char *name) {
     40   BlockingMutexLock lock(&mutex_);
     41   // Try to match suppressions with symlink target.
     42   InternalScopedString buf(kMaxPathLength);
     43   if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
     44       buf[0]) {
     45     for (uptr i = 0; i < count_; i++) {
     46       Lib *lib = &libs_[i];
     47       if (!lib->loaded && (!lib->real_name) &&
     48           TemplateMatch(lib->templ, name))
     49         lib->real_name = internal_strdup(buf.data());
     50     }
     51   }
     52 
     53   // Scan suppressions list and find newly loaded and unloaded libraries.
     54   ListOfModules modules;
     55   modules.init();
     56   for (uptr i = 0; i < count_; i++) {
     57     Lib *lib = &libs_[i];
     58     bool loaded = false;
     59     for (const auto &mod : modules) {
     60       for (const auto &range : mod.ranges()) {
     61         if (!range.executable)
     62           continue;
     63         if (!TemplateMatch(lib->templ, mod.full_name()) &&
     64             !(lib->real_name &&
     65             internal_strcmp(lib->real_name, mod.full_name()) == 0))
     66           continue;
     67         if (loaded) {
     68           Report("%s: called_from_lib suppression '%s' is matched against"
     69                  " 2 libraries: '%s' and '%s'\n",
     70                  SanitizerToolName, lib->templ, lib->name, mod.full_name());
     71           Die();
     72         }
     73         loaded = true;
     74         if (lib->loaded)
     75           continue;
     76         VReport(1,
     77                 "Matched called_from_lib suppression '%s' against library"
     78                 " '%s'\n",
     79                 lib->templ, mod.full_name());
     80         lib->loaded = true;
     81         lib->name = internal_strdup(mod.full_name());
     82         const uptr idx =
     83             atomic_load(&ignored_ranges_count_, memory_order_relaxed);
     84         CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
     85         ignored_code_ranges_[idx].begin = range.beg;
     86         ignored_code_ranges_[idx].end = range.end;
     87         atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
     88         break;
     89       }
     90     }
     91     if (lib->loaded && !loaded) {
     92       Report("%s: library '%s' that was matched against called_from_lib"
     93              " suppression '%s' is unloaded\n",
     94              SanitizerToolName, lib->name, lib->templ);
     95       Die();
     96     }
     97   }
     98 
     99   // Track instrumented ranges.
    100   if (track_instrumented_libs_) {
    101     for (const auto &mod : modules) {
    102       if (!mod.instrumented())
    103         continue;
    104       for (const auto &range : mod.ranges()) {
    105         if (!range.executable)
    106           continue;
    107         if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
    108           continue;
    109         VReport(1, "Adding instrumented range %p-%p from library '%s'\n",
    110                 range.beg, range.end, mod.full_name());
    111         const uptr idx =
    112             atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
    113         CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
    114         instrumented_code_ranges_[idx].begin = range.beg;
    115         instrumented_code_ranges_[idx].end = range.end;
    116         atomic_store(&instrumented_ranges_count_, idx + 1,
    117                      memory_order_release);
    118       }
    119     }
    120   }
    121 }
    122 
    123 void LibIgnore::OnLibraryUnloaded() {
    124   OnLibraryLoaded(nullptr);
    125 }
    126 
    127 } // namespace __sanitizer
    128 
    129 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_MAC ||
    130         // SANITIZER_NETBSD
    131