xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/mapping_tracker.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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