xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/common/virtual_memory_mapping.cc (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 #include "src/trace_processor/importers/common/virtual_memory_mapping.h"
18 
19 #include <cstddef>
20 #include <cstdint>
21 #include <memory>
22 #include <optional>
23 #include <string>
24 #include <utility>
25 
26 #include "perfetto/base/logging.h"
27 #include "perfetto/ext/base/string_view.h"
28 #include "src/trace_processor/importers/common/address_range.h"
29 #include "src/trace_processor/importers/common/jit_cache.h"
30 #include "src/trace_processor/importers/common/stack_profile_tracker.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "src/trace_processor/tables/profiler_tables_py.h"
33 #include "src/trace_processor/types/trace_processor_context.h"
34 #include "src/trace_processor/util/build_id.h"
35 
36 namespace perfetto {
37 namespace trace_processor {
38 namespace {
39 
CreateMapping(TraceProcessorContext * context,const CreateMappingParams & params)40 MappingId CreateMapping(TraceProcessorContext* context,
41                         const CreateMappingParams& params) {
42   StringId build_id = context->storage->InternString(base::StringView(
43       params.build_id ? params.build_id->ToHex() : std::string()));
44   MappingId mapping_id =
45       context->storage->mutable_stack_profile_mapping_table()
46           ->Insert(
47               {build_id, static_cast<int64_t>(params.exact_offset),
48                static_cast<int64_t>(params.start_offset),
49                static_cast<int64_t>(params.memory_range.start()),
50                static_cast<int64_t>(params.memory_range.end()),
51                static_cast<int64_t>(params.load_bias),
52                context->storage->InternString(base::StringView(params.name))})
53           .id;
54 
55   return mapping_id;
56 }
57 
58 }  // namespace
59 
VirtualMemoryMapping(TraceProcessorContext * context,CreateMappingParams params)60 VirtualMemoryMapping::VirtualMemoryMapping(TraceProcessorContext* context,
61                                            CreateMappingParams params)
62     : context_(context),
63       mapping_id_(CreateMapping(context, params)),
64       memory_range_(params.memory_range),
65       offset_(params.exact_offset),
66       load_bias_(params.load_bias),
67       name_(std::move(params.name)),
68       build_id_(std::move(params.build_id)) {}
69 
70 VirtualMemoryMapping::~VirtualMemoryMapping() = default;
71 
KernelMemoryMapping(TraceProcessorContext * context,CreateMappingParams params)72 KernelMemoryMapping::KernelMemoryMapping(TraceProcessorContext* context,
73                                          CreateMappingParams params)
74     : VirtualMemoryMapping(context, std::move(params)) {}
75 
76 KernelMemoryMapping::~KernelMemoryMapping() = default;
77 
UserMemoryMapping(TraceProcessorContext * context,UniquePid upid,CreateMappingParams params)78 UserMemoryMapping::UserMemoryMapping(TraceProcessorContext* context,
79                                      UniquePid upid,
80                                      CreateMappingParams params)
81     : VirtualMemoryMapping(context, std::move(params)), upid_(upid) {}
82 
83 UserMemoryMapping::~UserMemoryMapping() = default;
84 
InternFrame(uint64_t rel_pc,base::StringView function_name)85 FrameId VirtualMemoryMapping::InternFrame(uint64_t rel_pc,
86                                           base::StringView function_name) {
87   auto [frame_id, was_inserted] =
88       jit_cache_ ? jit_cache_->InternFrame(this, rel_pc, function_name)
89                  : InternFrameImpl(rel_pc, function_name);
90   if (was_inserted) {
91     frames_by_rel_pc_[rel_pc].push_back(frame_id);
92     context_->stack_profile_tracker->OnFrameCreated(frame_id);
93   }
94   return frame_id;
95 }
96 
FindFrameIds(uint64_t rel_pc) const97 std::vector<FrameId> VirtualMemoryMapping::FindFrameIds(uint64_t rel_pc) const {
98   if (auto* res = frames_by_rel_pc_.Find(rel_pc); res != nullptr) {
99     return *res;
100   }
101   return {};
102 }
103 
InternFrameImpl(uint64_t rel_pc,base::StringView function_name)104 std::pair<FrameId, bool> VirtualMemoryMapping::InternFrameImpl(
105     uint64_t rel_pc,
106     base::StringView function_name) {
107   const FrameKey frame_key{rel_pc,
108                            context_->storage->InternString(function_name)};
109   if (FrameId* id = interned_frames_.Find(frame_key); id) {
110     return {*id, false};
111   }
112 
113   const FrameId frame_id =
114       context_->storage->mutable_stack_profile_frame_table()
115           ->Insert(
116               {frame_key.name_id, mapping_id_, static_cast<int64_t>(rel_pc)})
117           .id;
118   interned_frames_.Insert(frame_key, frame_id);
119 
120   return {frame_id, true};
121 }
122 
123 DummyMemoryMapping::~DummyMemoryMapping() = default;
124 
DummyMemoryMapping(TraceProcessorContext * context,CreateMappingParams params)125 DummyMemoryMapping::DummyMemoryMapping(TraceProcessorContext* context,
126                                        CreateMappingParams params)
127     : VirtualMemoryMapping(context, std::move(params)) {}
128 
InternDummyFrame(base::StringView function_name,base::StringView source_file)129 FrameId DummyMemoryMapping::InternDummyFrame(base::StringView function_name,
130                                              base::StringView source_file) {
131   DummyFrameKey key{context()->storage->InternString(function_name),
132                     context()->storage->InternString(source_file)};
133 
134   if (FrameId* id = interned_dummy_frames_.Find(key); id) {
135     return *id;
136   }
137 
138   uint32_t symbol_set_id = context()->storage->symbol_table().row_count();
139 
140   tables::SymbolTable::Id symbol_id =
141       context()
142           ->storage->mutable_symbol_table()
143           ->Insert({symbol_set_id, key.function_name_id, key.source_file_id})
144           .id;
145 
146   PERFETTO_CHECK(symbol_set_id == symbol_id.value);
147 
148   const FrameId frame_id =
149       context()
150           ->storage->mutable_stack_profile_frame_table()
151           ->Insert({key.function_name_id, mapping_id(), 0, symbol_set_id})
152           .id;
153   interned_dummy_frames_.Insert(key, frame_id);
154 
155   return frame_id;
156 }
157 
158 }  // namespace trace_processor
159 }  // namespace perfetto
160