diff options
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc')
| -rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc new file mode 100644 index 00000000000..9a0213e7b2b --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cc @@ -0,0 +1,85 @@ +//===-- sanitizer_libignore.cc --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#if SANITIZER_LINUX + +#include "sanitizer_libignore.h" +#include "sanitizer_procmaps.h" + +namespace __sanitizer { + +LibIgnore::LibIgnore(LinkerInitialized) { +} + +void LibIgnore::Init(const SuppressionContext &supp) { + BlockingMutexLock lock(&mutex_); + CHECK_EQ(count_, 0); + const uptr n = supp.SuppressionCount(); + for (uptr i = 0; i < n; i++) { + const Suppression *s = supp.SuppressionAt(i); + if (s->type != SuppressionLib) + continue; + if (count_ >= kMaxLibs) { + Report("%s: too many called_from_lib suppressions (max: %d)\n", + SanitizerToolName, kMaxLibs); + Die(); + } + Lib *lib = &libs_[count_++]; + lib->templ = internal_strdup(s->templ); + lib->name = 0; + lib->loaded = false; + } +} + +void LibIgnore::OnLibraryLoaded() { + BlockingMutexLock lock(&mutex_); + MemoryMappingLayout proc_maps(/*cache_enabled*/false); + InternalScopedBuffer<char> fn(4096); + for (uptr i = 0; i < count_; i++) { + Lib *lib = &libs_[i]; + bool loaded = false; + proc_maps.Reset(); + uptr b, e, off, prot; + while (proc_maps.Next(&b, &e, &off, fn.data(), fn.size(), &prot)) { + if ((prot & MemoryMappingLayout::kProtectionExecute) != 0 && + TemplateMatch(lib->templ, fn.data())) { + if (loaded) { + Report("%s: called_from_lib suppression '%s' is matched against" + " 2 libraries: '%s' and '%s'\n", + SanitizerToolName, lib->templ, lib->name, fn.data()); + Die(); + } + loaded = true; + if (!lib->loaded) { + lib->loaded = true; + lib->name = internal_strdup(fn.data()); + const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed); + code_ranges_[idx].begin = b; + code_ranges_[idx].end = e; + atomic_store(&loaded_count_, idx + 1, memory_order_release); + } + } + } + if (lib->loaded && !loaded) { + Report("%s: library '%s' that was matched against called_from_lib" + " suppression '%s' is unloaded\n", + SanitizerToolName, lib->name, lib->templ); + Die(); + } + } +} + +void LibIgnore::OnLibraryUnloaded() { + OnLibraryLoaded(); +} + +} // namespace __sanitizer + +#endif // #if SANITIZER_LINUX |

