1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ 19 20 #include <cstddef> 21 #include <cstdint> 22 #include <memory> 23 #include <optional> 24 #include <vector> 25 26 #include "perfetto/ext/base/flat_hash_map.h" 27 #include "perfetto/ext/base/hash.h" 28 #include "perfetto/ext/base/string_view.h" 29 #include "src/trace_processor/importers/common/address_range.h" 30 #include "src/trace_processor/importers/common/virtual_memory_mapping.h" 31 #include "src/trace_processor/storage/trace_storage.h" 32 #include "src/trace_processor/types/trace_processor_context.h" 33 #include "src/trace_processor/util/build_id.h" 34 35 namespace perfetto { 36 namespace trace_processor { 37 38 class JitCache; 39 40 // Keeps track of all aspects relative to memory mappings. 41 // This class keeps track of 3 types of mappings: UserMemoryMapping, 42 // KernelMemoryMapping and others. The others are used to represent mapping 43 // where we do not have enough information to determine what type of 44 // mapping (user, kernel) we are dealing with. This is usually the case with 45 // data sources that do not provide enough information about the mappings. 46 // 47 // TODO(carlscab): Hopefully we can slowly get rid of cases where these other 48 // mappings are needed. The biggest blocker right now is determining the upid. 49 // we could infer this from the actual samples that use said mapping (those 50 // usually have a pid attached). So we would need to have a "fake" mapping that 51 // actually materializes when we see a sample with a pid. 52 // 53 // ATTENTION: No overlaps allowed (for now). Eventually the order in which 54 // mappings are create will matter as newer mappings will delete old ones. 55 // This is how tools like linux perf behave, mmap event have a timestamp 56 // associated and there are no "delete events" just new mmap events that 57 // overlap (to be deleted) mappings. 58 class MappingTracker { 59 public: MappingTracker(TraceProcessorContext * context)60 explicit MappingTracker(TraceProcessorContext* context) : context_(context) {} 61 62 // Create a new kernel space mapping. Returned reference will be valid for the 63 // duration of this instance. 64 KernelMemoryMapping& CreateKernelMemoryMapping(CreateMappingParams params); 65 66 // Create a new user space mapping. Returned reference will be valid for the 67 // duration of this instance. 68 UserMemoryMapping& CreateUserMemoryMapping(UniquePid upid, 69 CreateMappingParams params); 70 71 // Sometimes we just need a mapping and we are lacking trace data to create a 72 // proper one. Use this mapping in those cases. 73 DummyMemoryMapping& CreateDummyMapping(std::string name); 74 75 // Create an "other" mapping. Returned reference will be valid for the 76 // duration of this instance. 77 VirtualMemoryMapping& InternMemoryMapping(CreateMappingParams params); 78 79 // Given an absolute address find the kernel mapping where this address 80 // belongs to. Returns `nullptr` if none is found. 81 KernelMemoryMapping* FindKernelMappingForAddress(uint64_t address) const; 82 83 // Given an absolute address find the user mapping where this address 84 // belongs to. Returns `nullptr` if none is found. 85 UserMemoryMapping* FindUserMappingForAddress(UniquePid upid, 86 uint64_t address) const; 87 88 std::vector<VirtualMemoryMapping*> FindMappings( 89 base::StringView name, 90 const BuildId& build_id) const; 91 92 // Marks a range of memory as containing jitted code. 93 // If the added region overlaps with other existing ranges the latter are all 94 // deleted. 95 // Jitted ranges will only be applied to UserMemoryMappings 96 void AddJitRange(UniquePid upid, AddressRange range, JitCache* jit_cache); 97 98 private: 99 template <typename MappingImpl> 100 MappingImpl& AddMapping(std::unique_ptr<MappingImpl> mapping); 101 102 TraceProcessorContext* const context_; 103 base::FlatHashMap<MappingId, std::unique_ptr<VirtualMemoryMapping>> 104 mappings_by_id_; 105 106 base::FlatHashMap<CreateMappingParams, 107 VirtualMemoryMapping*, 108 CreateMappingParams::Hasher> 109 interned_mappings_; 110 111 struct NameAndBuildId { 112 base::StringView name; 113 std::optional<BuildId> build_id; 114 115 bool operator==(const NameAndBuildId& o) const { 116 return name == o.name && build_id == o.build_id; 117 } 118 119 bool operator!=(const NameAndBuildId& o) const { return !(*this == o); } 120 121 struct Hasher { operatorNameAndBuildId::Hasher122 size_t operator()(const NameAndBuildId& o) const { 123 base::Hasher hasher; 124 hasher.Update(o.name); 125 if (o.build_id) { 126 hasher.Update(*o.build_id); 127 } 128 return static_cast<size_t>(hasher.digest()); 129 } 130 }; 131 }; 132 base::FlatHashMap<NameAndBuildId, 133 std::vector<VirtualMemoryMapping*>, 134 NameAndBuildId::Hasher> 135 mappings_by_name_and_build_id_; 136 137 base::FlatHashMap<UniquePid, AddressRangeMap<UserMemoryMapping*>> 138 user_memory_; 139 AddressRangeMap<KernelMemoryMapping*> kernel_modules_; 140 KernelMemoryMapping* kernel_ = nullptr; 141 142 base::FlatHashMap<UniquePid, AddressRangeMap<JitCache*>> jit_caches_; 143 }; 144 145 } // namespace trace_processor 146 } // namespace perfetto 147 148 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_MAPPING_TRACKER_H_ 149