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