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