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 17 namespace __sanitizer { 18 19 LibIgnore::LibIgnore(LinkerInitialized) { 20 } 21 22 void 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 42 void 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 VReport(1, 80 "Matched called_from_lib suppression '%s' against library" 81 " '%s'\n", 82 lib->templ, module.data()); 83 lib->loaded = true; 84 lib->name = internal_strdup(module.data()); 85 const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed); 86 code_ranges_[idx].begin = b; 87 code_ranges_[idx].end = e; 88 atomic_store(&loaded_count_, idx + 1, memory_order_release); 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 100 void LibIgnore::OnLibraryUnloaded() { 101 OnLibraryLoaded(0); 102 } 103 104 } // namespace __sanitizer 105 106 #endif // #if SANITIZER_LINUX 107