• 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 
20 #include "perfetto/ext/base/optional.h"
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     }
117     return "unknown";  // switch should be complete, but gcc needs a hint
118   }
119 };
120 
121 class ProfilePacketInternLookup
122     : public SequenceStackProfileTracker::InternLookup {
123  public:
ProfilePacketInternLookup(PacketSequenceStateGeneration * seq_state)124   explicit ProfilePacketInternLookup(PacketSequenceStateGeneration* seq_state)
125       : seq_state_(seq_state) {}
126   ~ProfilePacketInternLookup() override;
127 
GetString(SequenceStackProfileTracker::SourceStringId iid,SequenceStackProfileTracker::InternedStringType type)128   base::Optional<base::StringView> GetString(
129       SequenceStackProfileTracker::SourceStringId iid,
130       SequenceStackProfileTracker::InternedStringType type) const override {
131     protos::pbzero::InternedString::Decoder* decoder = nullptr;
132     switch (type) {
133       case SequenceStackProfileTracker::InternedStringType::kBuildId:
134         decoder = seq_state_->LookupInternedMessage<
135             protos::pbzero::InternedData::kBuildIdsFieldNumber,
136             protos::pbzero::InternedString>(iid);
137         break;
138       case SequenceStackProfileTracker::InternedStringType::kFunctionName:
139         decoder = seq_state_->LookupInternedMessage<
140             protos::pbzero::InternedData::kFunctionNamesFieldNumber,
141             protos::pbzero::InternedString>(iid);
142         break;
143       case SequenceStackProfileTracker::InternedStringType::kMappingPath:
144         decoder = seq_state_->LookupInternedMessage<
145             protos::pbzero::InternedData::kMappingPathsFieldNumber,
146             protos::pbzero::InternedString>(iid);
147         break;
148     }
149     if (!decoder)
150       return base::nullopt;
151     return base::StringView(reinterpret_cast<const char*>(decoder->str().data),
152                             decoder->str().size);
153   }
154 
GetMapping(SequenceStackProfileTracker::SourceMappingId iid)155   base::Optional<SequenceStackProfileTracker::SourceMapping> GetMapping(
156       SequenceStackProfileTracker::SourceMappingId iid) const override {
157     auto* decoder = seq_state_->LookupInternedMessage<
158         protos::pbzero::InternedData::kMappingsFieldNumber,
159         protos::pbzero::Mapping>(iid);
160     if (!decoder)
161       return base::nullopt;
162     return ProfilePacketUtils::MakeSourceMapping(*decoder);
163   }
164 
GetFrame(SequenceStackProfileTracker::SourceFrameId iid)165   base::Optional<SequenceStackProfileTracker::SourceFrame> GetFrame(
166       SequenceStackProfileTracker::SourceFrameId iid) const override {
167     auto* decoder = seq_state_->LookupInternedMessage<
168         protos::pbzero::InternedData::kFramesFieldNumber,
169         protos::pbzero::Frame>(iid);
170     if (!decoder)
171       return base::nullopt;
172     return ProfilePacketUtils::MakeSourceFrame(*decoder);
173   }
174 
GetCallstack(SequenceStackProfileTracker::SourceCallstackId iid)175   base::Optional<SequenceStackProfileTracker::SourceCallstack> GetCallstack(
176       SequenceStackProfileTracker::SourceCallstackId iid) const override {
177     auto* interned_message_view = seq_state_->GetInternedMessageView(
178         protos::pbzero::InternedData::kCallstacksFieldNumber, iid);
179     if (!interned_message_view)
180       return base::nullopt;
181     protos::pbzero::Callstack::Decoder decoder(
182         interned_message_view->message().data(),
183         interned_message_view->message().length());
184     return ProfilePacketUtils::MakeSourceCallstack(std::move(decoder));
185   }
186 
187  private:
188   PacketSequenceStateGeneration* seq_state_;
189 };
190 
191 }  // namespace trace_processor
192 }  // namespace perfetto
193 
194 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROFILE_PACKET_UTILS_H_
195