sanitizer_libignore.cc revision e6f3247020e4710eda6fb210c9fa3c56647b4ca6
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#if SANITIZER_LINUX 12 13#include "sanitizer_libignore.h" 14#include "sanitizer_flags.h" 15#include "sanitizer_procmaps.h" 16 17namespace __sanitizer { 18 19LibIgnore::LibIgnore(LinkerInitialized) { 20} 21 22void LibIgnore::Init(const SuppressionContext &supp) { 23 BlockingMutexLock lock(&mutex_); 24 CHECK_EQ(count_, 0); 25 const uptr n = supp.SuppressionCount(); 26 for (uptr i = 0; i < n; i++) { 27 const Suppression *s = supp.SuppressionAt(i); 28 if (s->type != SuppressionLib) 29 continue; 30 if (count_ >= kMaxLibs) { 31 Report("%s: too many called_from_lib suppressions (max: %d)\n", 32 SanitizerToolName, kMaxLibs); 33 Die(); 34 } 35 Lib *lib = &libs_[count_++]; 36 lib->templ = internal_strdup(s->templ); 37 lib->name = 0; 38 lib->loaded = false; 39 } 40} 41 42void LibIgnore::OnLibraryLoaded(const char *name) { 43 BlockingMutexLock lock(&mutex_); 44 // Try to match suppressions with symlink target. 45 InternalScopedBuffer<char> buf(4096); 46 if (name != 0 && internal_readlink(name, buf.data(), buf.size() - 1) > 0 && 47 buf.data()[0]) { 48 for (uptr i = 0; i < count_; i++) { 49 Lib *lib = &libs_[i]; 50 if (!lib->loaded && lib->real_name == 0 && 51 TemplateMatch(lib->templ, name)) 52 lib->real_name = internal_strdup(buf.data()); 53 } 54 } 55 56 // Scan suppressions list and find newly loaded and unloaded libraries. 57 MemoryMappingLayout proc_maps(/*cache_enabled*/false); 58 InternalScopedBuffer<char> module(4096); 59 for (uptr i = 0; i < count_; i++) { 60 Lib *lib = &libs_[i]; 61 bool loaded = false; 62 proc_maps.Reset(); 63 uptr b, e, off, prot; 64 while (proc_maps.Next(&b, &e, &off, module.data(), module.size(), &prot)) { 65 if ((prot & MemoryMappingLayout::kProtectionExecute) == 0) 66 continue; 67 if (TemplateMatch(lib->templ, module.data()) || 68 (lib->real_name != 0 && 69 internal_strcmp(lib->real_name, module.data()) == 0)) { 70 if (loaded) { 71 Report("%s: called_from_lib suppression '%s' is matched against" 72 " 2 libraries: '%s' and '%s'\n", 73 SanitizerToolName, lib->templ, lib->name, module.data()); 74 Die(); 75 } 76 loaded = true; 77 if (lib->loaded) 78 continue; 79 if (common_flags()->verbosity) 80 Report("Matched called_from_lib suppression '%s' against library" 81 " '%s'\n", lib->templ, module.data()); 82 lib->loaded = true; 83 lib->name = internal_strdup(module.data()); 84 const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed); 85 code_ranges_[idx].begin = b; 86 code_ranges_[idx].end = e; 87 atomic_store(&loaded_count_, idx + 1, memory_order_release); 88 } 89 } 90 if (lib->loaded && !loaded) { 91 Report("%s: library '%s' that was matched against called_from_lib" 92 " suppression '%s' is unloaded\n", 93 SanitizerToolName, lib->name, lib->templ); 94 Die(); 95 } 96 } 97} 98 99void LibIgnore::OnLibraryUnloaded() { 100 OnLibraryLoaded(0); 101} 102 103} // namespace __sanitizer 104 105#endif // #if SANITIZER_LINUX 106