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