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