• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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_PROTO_PROFILE_PACKET_UTILS_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILE_PACKET_UTILS_H_
19 #include <optional>
20 
21 #include "perfetto/ext/base/string_view.h"
22 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
23 #include "src/trace_processor/importers/proto/stack_profile_tracker.h"
24 
25 #include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
26 #include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
27 #include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
28 
29 namespace perfetto {
30 namespace trace_processor {
31 
32 class ProfilePacketUtils {
33  public:
MakeSourceMapping(const protos::pbzero::Mapping::Decoder & entry)34   static SequenceStackProfileTracker::SourceMapping MakeSourceMapping(
35       const protos::pbzero::Mapping::Decoder& entry) {
36     SequenceStackProfileTracker::SourceMapping src_mapping{};
37     src_mapping.build_id = entry.build_id();
38     src_mapping.exact_offset = entry.exact_offset();
39     src_mapping.start_offset = entry.start_offset();
40     src_mapping.start = entry.start();
41     src_mapping.end = entry.end();
42     src_mapping.load_bias = entry.load_bias();
43     for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
44          ++path_string_id_it) {
45       src_mapping.name_ids.emplace_back(*path_string_id_it);
46     }
47     return src_mapping;
48   }
49 
MakeSourceFrame(const protos::pbzero::Frame::Decoder & entry)50   static SequenceStackProfileTracker::SourceFrame MakeSourceFrame(
51       const protos::pbzero::Frame::Decoder& entry) {
52     SequenceStackProfileTracker::SourceFrame src_frame;
53     src_frame.name_id = entry.function_name_id();
54     src_frame.mapping_id = entry.mapping_id();
55     src_frame.rel_pc = entry.rel_pc();
56     return src_frame;
57   }
58 
MakeSourceCallstack(const protos::pbzero::Callstack::Decoder & entry)59   static SequenceStackProfileTracker::SourceCallstack MakeSourceCallstack(
60       const protos::pbzero::Callstack::Decoder& entry) {
61     SequenceStackProfileTracker::SourceCallstack src_callstack;
62     for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
63       src_callstack.emplace_back(*frame_it);
64     return src_callstack;
65   }
66 
StringifyCpuMode(protos::pbzero::Profiling::CpuMode cpu_mode)67   static const char* StringifyCpuMode(
68       protos::pbzero::Profiling::CpuMode cpu_mode) {
69     using protos::pbzero::Profiling;
70     switch (cpu_mode) {
71       case Profiling::MODE_UNKNOWN:
72         return "unknown";
73       case Profiling::MODE_KERNEL:
74         return "kernel";
75       case Profiling::MODE_USER:
76         return "user";
77       case Profiling::MODE_HYPERVISOR:
78         return "hypervisor";
79       case Profiling::MODE_GUEST_KERNEL:
80         return "guest_kernel";
81       case Profiling::MODE_GUEST_USER:
82         return "guest_user";
83     }
84     return "unknown";  // switch should be complete, but gcc needs a hint
85   }
86 
StringifyStackUnwindError(protos::pbzero::Profiling::StackUnwindError unwind_error)87   static const char* StringifyStackUnwindError(
88       protos::pbzero::Profiling::StackUnwindError unwind_error) {
89     using protos::pbzero::Profiling;
90     switch (unwind_error) {
91       case Profiling::UNWIND_ERROR_UNKNOWN:
92         return "unknown";
93       case Profiling::UNWIND_ERROR_NONE:
94         return "none";  // should never see this serialized by traced_perf, the
95                         // field should be unset instead
96       case Profiling::UNWIND_ERROR_MEMORY_INVALID:
97         return "memory_invalid";
98       case Profiling::UNWIND_ERROR_UNWIND_INFO:
99         return "unwind_info";
100       case Profiling::UNWIND_ERROR_UNSUPPORTED:
101         return "unsupported";
102       case Profiling::UNWIND_ERROR_INVALID_MAP:
103         return "invalid_map";
104       case Profiling::UNWIND_ERROR_MAX_FRAMES_EXCEEDED:
105         return "max_frames_exceeded";
106       case Profiling::UNWIND_ERROR_REPEATED_FRAME:
107         return "repeated_frame";
108       case Profiling::UNWIND_ERROR_INVALID_ELF:
109         return "invalid_elf";
110       case Profiling::UNWIND_ERROR_SYSTEM_CALL:
111         return "system_call";
112       case Profiling::UNWIND_ERROR_THREAD_TIMEOUT:
113         return "thread_timeout";
114       case Profiling::UNWIND_ERROR_THREAD_DOES_NOT_EXIST:
115         return "thread_does_not_exist";
116       case Profiling::UNWIND_ERROR_BAD_ARCH:
117         return "bad_arch";
118       case Profiling::UNWIND_ERROR_MAPS_PARSE:
119         return "maps_parse";
120       case Profiling::UNWIND_ERROR_INVALID_PARAMETER:
121         return "invalid_parameter";
122       case Profiling::UNWIND_ERROR_PTRACE_CALL:
123         return "ptrace_call";
124     }
125     return "unknown";  // switch should be complete, but gcc needs a hint
126   }
127 };
128 
129 class ProfilePacketInternLookup
130     : public SequenceStackProfileTracker::InternLookup {
131  public:
ProfilePacketInternLookup(PacketSequenceStateGeneration * seq_state)132   explicit ProfilePacketInternLookup(PacketSequenceStateGeneration* seq_state)
133       : seq_state_(seq_state) {}
134   ~ProfilePacketInternLookup() override;
135 
GetString(SequenceStackProfileTracker::SourceStringId iid,SequenceStackProfileTracker::InternedStringType type)136   std::optional<base::StringView> GetString(
137       SequenceStackProfileTracker::SourceStringId iid,
138       SequenceStackProfileTracker::InternedStringType type) const override {
139     protos::pbzero::InternedString::Decoder* decoder = nullptr;
140     switch (type) {
141       case SequenceStackProfileTracker::InternedStringType::kBuildId:
142         decoder = seq_state_->LookupInternedMessage<
143             protos::pbzero::InternedData::kBuildIdsFieldNumber,
144             protos::pbzero::InternedString>(iid);
145         break;
146       case SequenceStackProfileTracker::InternedStringType::kFunctionName:
147         decoder = seq_state_->LookupInternedMessage<
148             protos::pbzero::InternedData::kFunctionNamesFieldNumber,
149             protos::pbzero::InternedString>(iid);
150         break;
151       case SequenceStackProfileTracker::InternedStringType::kMappingPath:
152         decoder = seq_state_->LookupInternedMessage<
153             protos::pbzero::InternedData::kMappingPathsFieldNumber,
154             protos::pbzero::InternedString>(iid);
155         break;
156     }
157     if (!decoder)
158       return std::nullopt;
159     return base::StringView(reinterpret_cast<const char*>(decoder->str().data),
160                             decoder->str().size);
161   }
162 
GetMapping(SequenceStackProfileTracker::SourceMappingId iid)163   std::optional<SequenceStackProfileTracker::SourceMapping> GetMapping(
164       SequenceStackProfileTracker::SourceMappingId iid) const override {
165     auto* decoder = seq_state_->LookupInternedMessage<
166         protos::pbzero::InternedData::kMappingsFieldNumber,
167         protos::pbzero::Mapping>(iid);
168     if (!decoder)
169       return std::nullopt;
170     return ProfilePacketUtils::MakeSourceMapping(*decoder);
171   }
172 
GetFrame(SequenceStackProfileTracker::SourceFrameId iid)173   std::optional<SequenceStackProfileTracker::SourceFrame> GetFrame(
174       SequenceStackProfileTracker::SourceFrameId iid) const override {
175     auto* decoder = seq_state_->LookupInternedMessage<
176         protos::pbzero::InternedData::kFramesFieldNumber,
177         protos::pbzero::Frame>(iid);
178     if (!decoder)
179       return std::nullopt;
180     return ProfilePacketUtils::MakeSourceFrame(*decoder);
181   }
182 
GetCallstack(SequenceStackProfileTracker::SourceCallstackId iid)183   std::optional<SequenceStackProfileTracker::SourceCallstack> GetCallstack(
184       SequenceStackProfileTracker::SourceCallstackId iid) const override {
185     auto* interned_message_view = seq_state_->GetInternedMessageView(
186         protos::pbzero::InternedData::kCallstacksFieldNumber, iid);
187     if (!interned_message_view)
188       return std::nullopt;
189     protos::pbzero::Callstack::Decoder decoder(
190         interned_message_view->message().data(),
191         interned_message_view->message().length());
192     return ProfilePacketUtils::MakeSourceCallstack(std::move(decoder));
193   }
194 
195  private:
196   PacketSequenceStateGeneration* seq_state_;
197 };
198 
199 }  // namespace trace_processor
200 }  // namespace perfetto
201 
202 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILE_PACKET_UTILS_H_
203