1 /* 2 * Copyright (C) 2024 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_PERF_PERF_SESSION_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PERF_PERF_SESSION_H_ 19 20 #include <sys/types.h> 21 #include <cstddef> 22 #include <cstdint> 23 #include <optional> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 28 #include "perfetto/ext/base/flat_hash_map.h" 29 #include "perfetto/ext/base/hash.h" 30 #include "perfetto/ext/base/status_or.h" 31 #include "perfetto/trace_processor/ref_counted.h" 32 #include "perfetto/trace_processor/trace_blob_view.h" 33 #include "src/trace_processor/importers/perf/perf_event.h" 34 #include "src/trace_processor/importers/perf/perf_event_attr.h" 35 #include "src/trace_processor/tables/profiler_tables_py.h" 36 #include "src/trace_processor/util/build_id.h" 37 38 namespace perfetto::trace_processor { 39 40 class TraceProcessorContext; 41 42 namespace perf_importer { 43 44 // Helper to deal with perf_event_attr instances in a perf file. 45 class PerfSession : public RefCounted { 46 public: 47 class Builder { 48 public: Builder(TraceProcessorContext * context)49 explicit Builder(TraceProcessorContext* context) : context_(context) {} 50 base::StatusOr<RefPtr<PerfSession>> Build(); AddAttrAndIds(perf_event_attr attr,std::vector<uint64_t> ids)51 Builder& AddAttrAndIds(perf_event_attr attr, std::vector<uint64_t> ids) { 52 attr_with_ids_.push_back({attr, std::move(ids)}); 53 return *this; 54 } 55 56 private: 57 struct PerfEventAttrWithIds { 58 perf_event_attr attr; 59 std::vector<uint64_t> ids; 60 }; 61 TraceProcessorContext* const context_; 62 std::vector<PerfEventAttrWithIds> attr_with_ids_; 63 }; 64 perf_session_id()65 tables::PerfSessionTable::Id perf_session_id() const { 66 return perf_session_id_; 67 } 68 69 RefPtr<PerfEventAttr> FindAttrForEventId(uint64_t id) const; 70 71 base::StatusOr<RefPtr<PerfEventAttr>> FindAttrForRecord( 72 const perf_event_header& header, 73 const TraceBlobView& payload) const; 74 75 void SetCmdline(const std::vector<std::string>& args); 76 void SetEventName(uint64_t event_id, std::string name); 77 void SetEventName(uint32_t type, uint64_t config, const std::string& name); 78 79 void AddBuildId(int32_t pid, std::string filename, BuildId build_id); 80 std::optional<BuildId> LookupBuildId(uint32_t pid, 81 const std::string& filename) const; 82 83 // The kernel stores the return address for non leaf frames in call chains. 84 // Simpleperf accounts for this when writing perf data files, linux perf does 85 // not. This method returns true if we need to convert return addresses to 86 // call sites when parsing call chains (i.e. if the trace comes from linux 87 // perf). needs_pc_adjustment()88 bool needs_pc_adjustment() const { return is_simpleperf_ == false; } 89 SetIsSimpleperf()90 void SetIsSimpleperf() { is_simpleperf_ = true; } 91 92 bool HasPerfClock() const; 93 94 private: 95 struct BuildIdMapKey { 96 int32_t pid; 97 std::string filename; 98 99 struct Hasher { operatorBuildIdMapKey::Hasher100 size_t operator()(const BuildIdMapKey& k) const { 101 return static_cast<size_t>(base::Hasher::Combine(k.pid, k.filename)); 102 } 103 }; 104 105 bool operator==(const BuildIdMapKey& o) const { 106 return pid == o.pid && filename == o.filename; 107 } 108 }; 109 PerfSession(TraceProcessorContext * context,tables::PerfSessionTable::Id perf_session_id,RefPtr<PerfEventAttr> first_attr,base::FlatHashMap<uint64_t,RefPtr<PerfEventAttr>> attrs_by_id,bool has_single_perf_event_attr)110 PerfSession(TraceProcessorContext* context, 111 tables::PerfSessionTable::Id perf_session_id, 112 RefPtr<PerfEventAttr> first_attr, 113 base::FlatHashMap<uint64_t, RefPtr<PerfEventAttr>> attrs_by_id, 114 bool has_single_perf_event_attr) 115 : context_(context), 116 perf_session_id_(perf_session_id), 117 first_attr_(std::move(first_attr)), 118 attrs_by_id_(std::move(attrs_by_id)), 119 has_single_perf_event_attr_(has_single_perf_event_attr) {} 120 121 bool ReadEventId(const perf_event_header& header, 122 const TraceBlobView& payload, 123 uint64_t& id) const; 124 125 TraceProcessorContext* const context_; 126 tables::PerfSessionTable::Id perf_session_id_; 127 RefPtr<PerfEventAttr> first_attr_; 128 base::FlatHashMap<uint64_t, RefPtr<PerfEventAttr>> attrs_by_id_; 129 130 // Multiple ids can map to the same perf_event_attr. This member tells us 131 // whether there was only one perf_event_attr (with potentially different ids 132 // associated). This makes the attr lookup given a record trivial and not 133 // dependant no having any id field in the records. 134 bool has_single_perf_event_attr_; 135 136 bool is_simpleperf_ = false; 137 138 base::FlatHashMap<BuildIdMapKey, BuildId, BuildIdMapKey::Hasher> build_ids_; 139 }; 140 141 } // namespace perf_importer 142 } // namespace perfetto::trace_processor 143 144 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PERF_PERF_SESSION_H_ 145