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