]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc
Merge llvm, clang, compiler-rt, libc++, lld, and lldb release_80 branch
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / sanitizer_common / sanitizer_libignore.cc
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