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