1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_PROFILER_MODULE_CACHE_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_PROFILER_MODULE_CACHE_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <memory> 9*6777b538SAndroid Build Coastguard Worker #include <set> 10*6777b538SAndroid Build Coastguard Worker #include <string> 11*6777b538SAndroid Build Coastguard Worker #include <string_view> 12*6777b538SAndroid Build Coastguard Worker #include <vector> 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_set.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h" 18*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 21*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_types.h" 22*6777b538SAndroid Build Coastguard Worker #endif 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker namespace base { 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker // Converts module id to match the id that the Google-internal symbol server 27*6777b538SAndroid Build Coastguard Worker // expects. 28*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::string TransformModuleIDToSymbolServerFormat( 29*6777b538SAndroid Build Coastguard Worker std::string_view module_id); 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // Supports cached lookup of modules by address, with caching based on module 32*6777b538SAndroid Build Coastguard Worker // address ranges. 33*6777b538SAndroid Build Coastguard Worker // 34*6777b538SAndroid Build Coastguard Worker // Cached lookup is necessary on Mac for performance, due to an inefficient 35*6777b538SAndroid Build Coastguard Worker // dladdr implementation. See https://crrev.com/487092. 36*6777b538SAndroid Build Coastguard Worker // 37*6777b538SAndroid Build Coastguard Worker // Cached lookup is beneficial on Windows to minimize use of the loader 38*6777b538SAndroid Build Coastguard Worker // lock. Note however that the cache retains a handle to looked-up modules for 39*6777b538SAndroid Build Coastguard Worker // its lifetime, which may result in pinning modules in memory that were 40*6777b538SAndroid Build Coastguard Worker // transiently loaded by the OS. 41*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT ModuleCache { 42*6777b538SAndroid Build Coastguard Worker public: 43*6777b538SAndroid Build Coastguard Worker // Module represents a binary module (executable or library) and its 44*6777b538SAndroid Build Coastguard Worker // associated state. 45*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT Module { 46*6777b538SAndroid Build Coastguard Worker public: 47*6777b538SAndroid Build Coastguard Worker Module() = default; 48*6777b538SAndroid Build Coastguard Worker virtual ~Module() = default; 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker Module(const Module&) = delete; 51*6777b538SAndroid Build Coastguard Worker Module& operator=(const Module&) = delete; 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker // Gets the base address of the module. 54*6777b538SAndroid Build Coastguard Worker virtual uintptr_t GetBaseAddress() const = 0; 55*6777b538SAndroid Build Coastguard Worker 56*6777b538SAndroid Build Coastguard Worker // Gets the opaque binary string that uniquely identifies a particular 57*6777b538SAndroid Build Coastguard Worker // program version with high probability. This is parsed from headers of the 58*6777b538SAndroid Build Coastguard Worker // loaded module. 59*6777b538SAndroid Build Coastguard Worker // For binaries generated by GNU tools: 60*6777b538SAndroid Build Coastguard Worker // Contents of the .note.gnu.build-id field. 61*6777b538SAndroid Build Coastguard Worker // On Windows: 62*6777b538SAndroid Build Coastguard Worker // GUID + AGE in the debug image headers of a module. 63*6777b538SAndroid Build Coastguard Worker virtual std::string GetId() const = 0; 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker // Gets the debug basename of the module. This is the basename of the PDB 66*6777b538SAndroid Build Coastguard Worker // file on Windows and the basename of the binary on other platforms. 67*6777b538SAndroid Build Coastguard Worker virtual FilePath GetDebugBasename() const = 0; 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker // Gets the size of the module. 70*6777b538SAndroid Build Coastguard Worker virtual size_t GetSize() const = 0; 71*6777b538SAndroid Build Coastguard Worker 72*6777b538SAndroid Build Coastguard Worker // True if this is a native module. 73*6777b538SAndroid Build Coastguard Worker virtual bool IsNative() const = 0; 74*6777b538SAndroid Build Coastguard Worker }; 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker // Interface for lazily creating a native module for a given |address|. The 77*6777b538SAndroid Build Coastguard Worker // provider is registered with RegisterAuxiliaryModuleProvider(). 78*6777b538SAndroid Build Coastguard Worker class AuxiliaryModuleProvider { 79*6777b538SAndroid Build Coastguard Worker public: 80*6777b538SAndroid Build Coastguard Worker AuxiliaryModuleProvider() = default; 81*6777b538SAndroid Build Coastguard Worker AuxiliaryModuleProvider(const AuxiliaryModuleProvider&) = delete; 82*6777b538SAndroid Build Coastguard Worker AuxiliaryModuleProvider& operator=(const AuxiliaryModuleProvider&) = delete; 83*6777b538SAndroid Build Coastguard Worker 84*6777b538SAndroid Build Coastguard Worker virtual std::unique_ptr<const Module> TryCreateModuleForAddress( 85*6777b538SAndroid Build Coastguard Worker uintptr_t address) = 0; 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker protected: 88*6777b538SAndroid Build Coastguard Worker ~AuxiliaryModuleProvider() = default; 89*6777b538SAndroid Build Coastguard Worker }; 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker ModuleCache(); 92*6777b538SAndroid Build Coastguard Worker ~ModuleCache(); 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // Gets the module containing |address| or nullptr if |address| is not within 95*6777b538SAndroid Build Coastguard Worker // a module. The returned module remains owned by and has the same lifetime as 96*6777b538SAndroid Build Coastguard Worker // the ModuleCache object. 97*6777b538SAndroid Build Coastguard Worker const Module* GetModuleForAddress(uintptr_t address); 98*6777b538SAndroid Build Coastguard Worker std::vector<const Module*> GetModules() const; 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard Worker // Updates the set of non-native modules maintained by the 101*6777b538SAndroid Build Coastguard Worker // ModuleCache. Non-native modules represent regions of non-native executable 102*6777b538SAndroid Build Coastguard Worker // code such as V8 generated code. 103*6777b538SAndroid Build Coastguard Worker // 104*6777b538SAndroid Build Coastguard Worker // Note that non-native modules may be embedded within native modules, as in 105*6777b538SAndroid Build Coastguard Worker // the case of V8 builtin code compiled within Chrome. In that case 106*6777b538SAndroid Build Coastguard Worker // GetModuleForAddress() will return the non-native module rather than the 107*6777b538SAndroid Build Coastguard Worker // native module for the memory region it occupies. 108*6777b538SAndroid Build Coastguard Worker // 109*6777b538SAndroid Build Coastguard Worker // Modules in |defunct_modules| are removed from the set of active modules; 110*6777b538SAndroid Build Coastguard Worker // specifically they no longer participate in the GetModuleForAddress() 111*6777b538SAndroid Build Coastguard Worker // lookup. They continue to exist for the lifetime of the ModuleCache, 112*6777b538SAndroid Build Coastguard Worker // however, so that existing references to them remain valid. Modules in 113*6777b538SAndroid Build Coastguard Worker // |new_modules| are added to the set of active non-native modules. Modules in 114*6777b538SAndroid Build Coastguard Worker // |new_modules| may not overlap with any non-native Modules already present 115*6777b538SAndroid Build Coastguard Worker // in ModuleCache, unless those modules are provided in |defunct_modules| in 116*6777b538SAndroid Build Coastguard Worker // the same call. 117*6777b538SAndroid Build Coastguard Worker void UpdateNonNativeModules( 118*6777b538SAndroid Build Coastguard Worker const std::vector<const Module*>& defunct_modules, 119*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<const Module>> new_modules); 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker // Adds a custom native module to the cache. This is intended to support 122*6777b538SAndroid Build Coastguard Worker // native modules that require custom handling. In general, native modules 123*6777b538SAndroid Build Coastguard Worker // will be found and added automatically when invoking GetModuleForAddress(). 124*6777b538SAndroid Build Coastguard Worker // |module| may not overlap with any native Modules already present in 125*6777b538SAndroid Build Coastguard Worker // ModuleCache. 126*6777b538SAndroid Build Coastguard Worker void AddCustomNativeModule(std::unique_ptr<const Module> module); 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker // Registers a custom module provider for lazily creating native modules. At 129*6777b538SAndroid Build Coastguard Worker // most one provider can be registered at any time, and the provider must be 130*6777b538SAndroid Build Coastguard Worker // unregistered before being destroyed. This is intended to support native 131*6777b538SAndroid Build Coastguard Worker // modules that require custom handling. In general, native modules will be 132*6777b538SAndroid Build Coastguard Worker // found and added automatically when invoking GetModuleForAddress(). If no 133*6777b538SAndroid Build Coastguard Worker // module is found, this provider will be used as fallback. 134*6777b538SAndroid Build Coastguard Worker void RegisterAuxiliaryModuleProvider( 135*6777b538SAndroid Build Coastguard Worker AuxiliaryModuleProvider* auxiliary_module_provider); 136*6777b538SAndroid Build Coastguard Worker 137*6777b538SAndroid Build Coastguard Worker // Unregisters the custom module provider. 138*6777b538SAndroid Build Coastguard Worker void UnregisterAuxiliaryModuleProvider( 139*6777b538SAndroid Build Coastguard Worker AuxiliaryModuleProvider* auxiliary_module_provider); 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Worker // Gets the module containing |address| if one already exists, or nullptr 142*6777b538SAndroid Build Coastguard Worker // otherwise. The returned module remains owned by and has the same lifetime 143*6777b538SAndroid Build Coastguard Worker // as the ModuleCache object. 144*6777b538SAndroid Build Coastguard Worker // NOTE: Only users that create their own modules and need control over native 145*6777b538SAndroid Build Coastguard Worker // module creation should use this function. Everyone else should use 146*6777b538SAndroid Build Coastguard Worker // GetModuleForAddress(). 147*6777b538SAndroid Build Coastguard Worker const Module* GetExistingModuleForAddress(uintptr_t address) const; 148*6777b538SAndroid Build Coastguard Worker 149*6777b538SAndroid Build Coastguard Worker private: 150*6777b538SAndroid Build Coastguard Worker // Heterogenously compares modules by base address, and modules and 151*6777b538SAndroid Build Coastguard Worker // addresses. The module/address comparison considers the address equivalent 152*6777b538SAndroid Build Coastguard Worker // to the module if the address is within the extent of the module. Combined 153*6777b538SAndroid Build Coastguard Worker // with is_transparent this allows modules to be looked up by address in the 154*6777b538SAndroid Build Coastguard Worker // using containers. 155*6777b538SAndroid Build Coastguard Worker struct ModuleAndAddressCompare { 156*6777b538SAndroid Build Coastguard Worker using is_transparent = void; 157*6777b538SAndroid Build Coastguard Worker bool operator()(const std::unique_ptr<const Module>& m1, 158*6777b538SAndroid Build Coastguard Worker const std::unique_ptr<const Module>& m2) const; 159*6777b538SAndroid Build Coastguard Worker bool operator()(const std::unique_ptr<const Module>& m1, 160*6777b538SAndroid Build Coastguard Worker uintptr_t address) const; 161*6777b538SAndroid Build Coastguard Worker bool operator()(uintptr_t address, 162*6777b538SAndroid Build Coastguard Worker const std::unique_ptr<const Module>& m2) const; 163*6777b538SAndroid Build Coastguard Worker }; 164*6777b538SAndroid Build Coastguard Worker 165*6777b538SAndroid Build Coastguard Worker // Creates a Module object for the specified memory address. Returns null if 166*6777b538SAndroid Build Coastguard Worker // the address does not belong to a module. 167*6777b538SAndroid Build Coastguard Worker static std::unique_ptr<const Module> CreateModuleForAddress( 168*6777b538SAndroid Build Coastguard Worker uintptr_t address); 169*6777b538SAndroid Build Coastguard Worker 170*6777b538SAndroid Build Coastguard Worker // Set of native modules sorted by base address. We use set rather than 171*6777b538SAndroid Build Coastguard Worker // flat_set because the latter type has O(n^2) runtime for adding modules 172*6777b538SAndroid Build Coastguard Worker // one-at-a-time, which is how modules are added on Windows and Mac. 173*6777b538SAndroid Build Coastguard Worker std::set<std::unique_ptr<const Module>, ModuleAndAddressCompare> 174*6777b538SAndroid Build Coastguard Worker native_modules_; 175*6777b538SAndroid Build Coastguard Worker 176*6777b538SAndroid Build Coastguard Worker // Set of non-native modules currently mapped into the address space, sorted 177*6777b538SAndroid Build Coastguard Worker // by base address. Represented as flat_set because std::set does not support 178*6777b538SAndroid Build Coastguard Worker // extracting move-only element types prior to C++17's 179*6777b538SAndroid Build Coastguard Worker // std::set<>::extract(). The non-native module insertion/removal patterns -- 180*6777b538SAndroid Build Coastguard Worker // initial bulk insertion, then infrequent inserts/removals -- should work 181*6777b538SAndroid Build Coastguard Worker // reasonably well with the flat_set complexity guarantees. Separate from 182*6777b538SAndroid Build Coastguard Worker // native_modules_ to support preferential lookup of non-native modules 183*6777b538SAndroid Build Coastguard Worker // embedded in native modules; see comment on UpdateNonNativeModules(). 184*6777b538SAndroid Build Coastguard Worker base::flat_set<std::unique_ptr<const Module>, ModuleAndAddressCompare> 185*6777b538SAndroid Build Coastguard Worker non_native_modules_; 186*6777b538SAndroid Build Coastguard Worker 187*6777b538SAndroid Build Coastguard Worker // Unsorted vector of inactive non-native modules. Inactive modules are no 188*6777b538SAndroid Build Coastguard Worker // longer mapped in the address space and don't participate in address lookup, 189*6777b538SAndroid Build Coastguard Worker // but are retained by the cache so that existing references to the them 190*6777b538SAndroid Build Coastguard Worker // remain valid. Note that this cannot be represented as a set/flat_set 191*6777b538SAndroid Build Coastguard Worker // because it can contain multiple modules that were loaded (then subsequently 192*6777b538SAndroid Build Coastguard Worker // unloaded) at the same base address. 193*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<const Module>> inactive_non_native_modules_; 194*6777b538SAndroid Build Coastguard Worker 195*6777b538SAndroid Build Coastguard Worker // Auxiliary module provider, for lazily creating native modules. 196*6777b538SAndroid Build Coastguard Worker raw_ptr<AuxiliaryModuleProvider> auxiliary_module_provider_ = nullptr; 197*6777b538SAndroid Build Coastguard Worker }; 198*6777b538SAndroid Build Coastguard Worker 199*6777b538SAndroid Build Coastguard Worker } // namespace base 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Worker #endif // BASE_PROFILER_MODULE_CACHE_H_ 202