13cab2bb3Spatrick //===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // LibIgnore allows to ignore all interceptors called from a particular set
103cab2bb3Spatrick // of dynamic libraries. LibIgnore can be initialized with several templates
113cab2bb3Spatrick // of names of libraries to be ignored. It finds code ranges for the libraries;
123cab2bb3Spatrick // and checks whether the provided PC value belongs to the code ranges.
133cab2bb3Spatrick //
143cab2bb3Spatrick //===----------------------------------------------------------------------===//
153cab2bb3Spatrick
163cab2bb3Spatrick #ifndef SANITIZER_LIBIGNORE_H
173cab2bb3Spatrick #define SANITIZER_LIBIGNORE_H
183cab2bb3Spatrick
193cab2bb3Spatrick #include "sanitizer_internal_defs.h"
203cab2bb3Spatrick #include "sanitizer_common.h"
213cab2bb3Spatrick #include "sanitizer_atomic.h"
223cab2bb3Spatrick #include "sanitizer_mutex.h"
233cab2bb3Spatrick
243cab2bb3Spatrick namespace __sanitizer {
253cab2bb3Spatrick
263cab2bb3Spatrick class LibIgnore {
273cab2bb3Spatrick public:
283cab2bb3Spatrick explicit LibIgnore(LinkerInitialized);
293cab2bb3Spatrick
303cab2bb3Spatrick // Must be called during initialization.
313cab2bb3Spatrick void AddIgnoredLibrary(const char *name_templ);
IgnoreNoninstrumentedModules(bool enable)323cab2bb3Spatrick void IgnoreNoninstrumentedModules(bool enable) {
333cab2bb3Spatrick track_instrumented_libs_ = enable;
343cab2bb3Spatrick }
353cab2bb3Spatrick
363cab2bb3Spatrick // Must be called after a new dynamic library is loaded.
373cab2bb3Spatrick void OnLibraryLoaded(const char *name);
383cab2bb3Spatrick
393cab2bb3Spatrick // Must be called after a dynamic library is unloaded.
403cab2bb3Spatrick void OnLibraryUnloaded();
413cab2bb3Spatrick
423cab2bb3Spatrick // Checks whether the provided PC belongs to one of the ignored libraries or
433cab2bb3Spatrick // the PC should be ignored because it belongs to an non-instrumented module
443cab2bb3Spatrick // (when ignore_noninstrumented_modules=1). Also returns true via
453cab2bb3Spatrick // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
463cab2bb3Spatrick bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
473cab2bb3Spatrick
483cab2bb3Spatrick // Checks whether the provided PC belongs to an instrumented module.
493cab2bb3Spatrick bool IsPcInstrumented(uptr pc) const;
503cab2bb3Spatrick
513cab2bb3Spatrick private:
523cab2bb3Spatrick struct Lib {
533cab2bb3Spatrick char *templ;
543cab2bb3Spatrick char *name;
553cab2bb3Spatrick char *real_name; // target of symlink
563cab2bb3Spatrick bool loaded;
573cab2bb3Spatrick };
583cab2bb3Spatrick
593cab2bb3Spatrick struct LibCodeRange {
603cab2bb3Spatrick uptr begin;
613cab2bb3Spatrick uptr end;
623cab2bb3Spatrick };
633cab2bb3Spatrick
IsInRange(uptr pc,const LibCodeRange & range)643cab2bb3Spatrick inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
653cab2bb3Spatrick return (pc >= range.begin && pc < range.end);
663cab2bb3Spatrick }
673cab2bb3Spatrick
683cab2bb3Spatrick static const uptr kMaxIgnoredRanges = 128;
693cab2bb3Spatrick static const uptr kMaxInstrumentedRanges = 1024;
703cab2bb3Spatrick static const uptr kMaxLibs = 1024;
713cab2bb3Spatrick
723cab2bb3Spatrick // Hot part:
733cab2bb3Spatrick atomic_uintptr_t ignored_ranges_count_;
743cab2bb3Spatrick LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
753cab2bb3Spatrick
763cab2bb3Spatrick atomic_uintptr_t instrumented_ranges_count_;
773cab2bb3Spatrick LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
783cab2bb3Spatrick
793cab2bb3Spatrick // Cold part:
80*810390e3Srobert Mutex mutex_;
813cab2bb3Spatrick uptr count_;
823cab2bb3Spatrick Lib libs_[kMaxLibs];
833cab2bb3Spatrick bool track_instrumented_libs_;
843cab2bb3Spatrick
853cab2bb3Spatrick // Disallow copying of LibIgnore objects.
863cab2bb3Spatrick LibIgnore(const LibIgnore&); // not implemented
873cab2bb3Spatrick void operator = (const LibIgnore&); // not implemented
883cab2bb3Spatrick };
893cab2bb3Spatrick
IsIgnored(uptr pc,bool * pc_in_ignored_lib)903cab2bb3Spatrick inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
913cab2bb3Spatrick const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
923cab2bb3Spatrick for (uptr i = 0; i < n; i++) {
933cab2bb3Spatrick if (IsInRange(pc, ignored_code_ranges_[i])) {
943cab2bb3Spatrick *pc_in_ignored_lib = true;
953cab2bb3Spatrick return true;
963cab2bb3Spatrick }
973cab2bb3Spatrick }
983cab2bb3Spatrick *pc_in_ignored_lib = false;
993cab2bb3Spatrick if (track_instrumented_libs_ && !IsPcInstrumented(pc))
1003cab2bb3Spatrick return true;
1013cab2bb3Spatrick return false;
1023cab2bb3Spatrick }
1033cab2bb3Spatrick
IsPcInstrumented(uptr pc)1043cab2bb3Spatrick inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
1053cab2bb3Spatrick const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
1063cab2bb3Spatrick for (uptr i = 0; i < n; i++) {
1073cab2bb3Spatrick if (IsInRange(pc, instrumented_code_ranges_[i]))
1083cab2bb3Spatrick return true;
1093cab2bb3Spatrick }
1103cab2bb3Spatrick return false;
1113cab2bb3Spatrick }
1123cab2bb3Spatrick
1133cab2bb3Spatrick } // namespace __sanitizer
1143cab2bb3Spatrick
1153cab2bb3Spatrick #endif // SANITIZER_LIBIGNORE_H
116