• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "src/trace_processor/importers/common/mapping_tracker.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <memory>
22 #include <utility>
23 
24 #include "perfetto/ext/base/string_utils.h"
25 #include "perfetto/ext/base/string_view.h"
26 #include "src/trace_processor/importers/common/address_range.h"
27 #include "src/trace_processor/importers/common/jit_cache.h"
28 #include "src/trace_processor/storage/trace_storage.h"
29 #include "src/trace_processor/types/trace_processor_context.h"
30 #include "src/trace_processor/util/build_id.h"
31 
32 namespace perfetto {
33 namespace trace_processor {
34 namespace {
35 
IsKernelModule(const CreateMappingParams & params)36 bool IsKernelModule(const CreateMappingParams& params) {
37   return !base::StartsWith(params.name, "[kernel.kallsyms]") &&
38          !params.memory_range.empty();
39 }
40 
41 }  // namespace
42 
43 template <typename MappingImpl>
AddMapping(std::unique_ptr<MappingImpl> mapping)44 MappingImpl& MappingTracker::AddMapping(std::unique_ptr<MappingImpl> mapping) {
45   auto ptr = mapping.get();
46   PERFETTO_CHECK(
47       mappings_by_id_.Insert(ptr->mapping_id(), std::move(mapping)).second);
48 
49   mappings_by_name_and_build_id_[NameAndBuildId{base::StringView(ptr->name()),
50                                                 ptr->build_id()}]
51       .push_back(ptr);
52 
53   return *ptr;
54 }
55 
CreateKernelMemoryMapping(CreateMappingParams params)56 KernelMemoryMapping& MappingTracker::CreateKernelMemoryMapping(
57     CreateMappingParams params) {
58   // TODO(carlscab): Guess build_id if not provided. Some tools like simpleperf
59   // add a mapping file_name ->build_id that we could use here
60 
61   const bool is_module = IsKernelModule(params);
62 
63   if (!is_module && kernel_ != nullptr) {
64     PERFETTO_CHECK(params.memory_range == kernel_->memory_range());
65     return *kernel_;
66   }
67 
68   std::unique_ptr<KernelMemoryMapping> mapping(
69       new KernelMemoryMapping(context_, std::move(params)));
70 
71   if (is_module) {
72     kernel_modules_.DeleteOverlapsAndEmplace(mapping->memory_range(),
73                                              mapping.get());
74   } else {
75     kernel_ = mapping.get();
76   }
77 
78   return AddMapping(std::move(mapping));
79 }
80 
CreateUserMemoryMapping(UniquePid upid,CreateMappingParams params)81 UserMemoryMapping& MappingTracker::CreateUserMemoryMapping(
82     UniquePid upid,
83     CreateMappingParams params) {
84   const AddressRange mapping_range = params.memory_range;
85   std::unique_ptr<UserMemoryMapping> mapping(
86       new UserMemoryMapping(context_, upid, std::move(params)));
87 
88   user_memory_[upid].DeleteOverlapsAndEmplace(mapping_range, mapping.get());
89 
90   jit_caches_[upid].ForOverlaps(
91       mapping_range, [&](std::pair<const AddressRange, JitCache*>& entry) {
92         const auto& jit_range = entry.first;
93         JitCache* jit_cache = entry.second;
94         PERFETTO_CHECK(jit_range.Contains(mapping_range));
95         mapping->SetJitCache(jit_cache);
96       });
97 
98   return AddMapping(std::move(mapping));
99 }
100 
FindKernelMappingForAddress(uint64_t address) const101 KernelMemoryMapping* MappingTracker::FindKernelMappingForAddress(
102     uint64_t address) const {
103   if (auto it = kernel_modules_.Find(address); it != kernel_modules_.end()) {
104     return it->second;
105   }
106   if (kernel_ && kernel_->memory_range().Contains(address)) {
107     return kernel_;
108   }
109   return nullptr;
110 }
111 
FindUserMappingForAddress(UniquePid upid,uint64_t address) const112 UserMemoryMapping* MappingTracker::FindUserMappingForAddress(
113     UniquePid upid,
114     uint64_t address) const {
115   if (auto* vm = user_memory_.Find(upid); vm) {
116     if (auto it = vm->Find(address); it != vm->end()) {
117       return it->second;
118     }
119   }
120 
121   if (auto* delegates = jit_caches_.Find(upid); delegates) {
122     if (auto it = delegates->Find(address); it != delegates->end()) {
123       return &it->second->CreateMapping();
124     }
125   }
126 
127   return nullptr;
128 }
129 
FindMappings(base::StringView name,const BuildId & build_id) const130 std::vector<VirtualMemoryMapping*> MappingTracker::FindMappings(
131     base::StringView name,
132     const BuildId& build_id) const {
133   if (auto res = mappings_by_name_and_build_id_.Find({name, build_id});
134       res != nullptr) {
135     return *res;
136   }
137   return {};
138 }
139 
InternMemoryMapping(CreateMappingParams params)140 VirtualMemoryMapping& MappingTracker::InternMemoryMapping(
141     CreateMappingParams params) {
142   if (auto* mapping = interned_mappings_.Find(params); mapping) {
143     return **mapping;
144   }
145 
146   std::unique_ptr<VirtualMemoryMapping> mapping(
147       new VirtualMemoryMapping(context_, params));
148   interned_mappings_.Insert(std::move(params), mapping.get());
149   return AddMapping(std::move(mapping));
150 }
151 
AddJitRange(UniquePid upid,AddressRange jit_range,JitCache * jit_cache)152 void MappingTracker::AddJitRange(UniquePid upid,
153                                  AddressRange jit_range,
154                                  JitCache* jit_cache) {
155   // TODO(carlscab): Deal with overlaps
156   jit_caches_[upid].DeleteOverlapsAndEmplace(jit_range, jit_cache);
157   user_memory_[upid].ForOverlaps(
158       jit_range, [&](std::pair<const AddressRange, UserMemoryMapping*>& entry) {
159         PERFETTO_CHECK(jit_range.Contains(entry.first));
160         entry.second->SetJitCache(jit_cache);
161       });
162 }
163 
GetDummyMapping()164 VirtualMemoryMapping* MappingTracker::GetDummyMapping() {
165   if (!dummy_mapping_) {
166     CreateMappingParams params;
167     params.memory_range =
168         AddressRange::FromStartAndSize(0, std::numeric_limits<uint64_t>::max());
169     dummy_mapping_ = &InternMemoryMapping(params);
170   }
171   return dummy_mapping_;
172 }
173 
174 }  // namespace trace_processor
175 }  // namespace perfetto
176