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