1// Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_ 6#define CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_ 7 8#include <stdint.h> 9 10#include <map> 11#include <set> 12#include <string> 13#include <utility> 14#include <vector> 15 16#include "base/macros.h" 17 18#include "perf_reader.h" 19#include "perf_utils.h" 20 21namespace quipper { 22 23class AddressMapper; 24 25// A struct containing all relevant info for a mapped DSO, independent of any 26// samples. 27struct DSOInfo { 28 string name; 29 string build_id; 30 31 // Comparator that allows this to be stored in a STL set. 32 bool operator<(const DSOInfo& other) const { 33 if (name == other.name) 34 return build_id < other.build_id; 35 return name < other.name; 36 } 37}; 38 39struct ParsedEvent { 40 // TODO(sque): Turn this struct into a class to privatize member variables. 41 ParsedEvent() : command_(NULL) {} 42 43 // Stores address of an event_t owned by the |PerfReader::events_| vector. 44 event_t* raw_event; 45 46 // For mmap events, use this to count the number of samples that are in this 47 // region. 48 uint32_t num_samples_in_mmap_region; 49 50 // Command associated with this sample. 51 const string* command_; 52 53 // Accessor for command string. 54 const string command() const { 55 if (command_) 56 return *command_; 57 return string(); 58 } 59 60 void set_command(const string* command) { 61 command_ = command; 62 } 63 64 // A struct that contains a DSO + offset pair. 65 struct DSOAndOffset { 66 const DSOInfo* dso_info_; 67 uint64_t offset_; 68 69 // Accessor methods. 70 const string dso_name() const { 71 if (dso_info_) 72 return dso_info_->name; 73 return string(); 74 } 75 const string build_id() const { 76 if (dso_info_) 77 return dso_info_->build_id; 78 return string(); 79 } 80 uint64_t offset() const { 81 return offset_; 82 } 83 84 DSOAndOffset() : dso_info_(NULL), 85 offset_(0) {} 86 } dso_and_offset; 87 88 // DSO+offset info for callchain. 89 std::vector<DSOAndOffset> callchain; 90 91 // DSO + offset info for branch stack entries. 92 struct BranchEntry { 93 bool predicted; 94 DSOAndOffset from; 95 DSOAndOffset to; 96 }; 97 std::vector<BranchEntry> branch_stack; 98}; 99 100struct PerfEventStats { 101 // Number of each type of event. 102 uint32_t num_sample_events; 103 uint32_t num_mmap_events; 104 uint32_t num_comm_events; 105 uint32_t num_fork_events; 106 uint32_t num_exit_events; 107 108 // Number of sample events that were successfully mapped using the address 109 // mapper. The mapping is recorded regardless of whether the address in the 110 // perf sample event itself was assigned the remapped address. The latter is 111 // indicated by |did_remap|. 112 uint32_t num_sample_events_mapped; 113 114 // Whether address remapping was enabled during event parsing. 115 bool did_remap; 116}; 117 118class PerfParser : public PerfReader { 119 public: 120 PerfParser(); 121 ~PerfParser(); 122 123 struct Options { 124 // For synthetic address mapping. 125 bool do_remap = false; 126 // Set this flag to discard non-sample events that don't have any associated 127 // sample events. e.g. MMAP regions with no samples in them. 128 bool discard_unused_events = false; 129 // When mapping perf sample events, at least this percentage of them must be 130 // successfully mapped in order for ProcessEvents() to return true. 131 // By default, most samples must be properly mapped in order for sample 132 // mapping to be considered successful. 133 float sample_mapping_percentage_threshold = 95.0f; 134 }; 135 136 // Constructor that takes in options at PerfParser creation time. 137 explicit PerfParser(const Options& options); 138 139 // Pass in a struct containing various options. 140 void set_options(const Options& options); 141 142 // Gets parsed event/sample info from raw event data. 143 bool ParseRawEvents(); 144 145 const std::vector<ParsedEvent>& parsed_events() const { 146 return parsed_events_; 147 } 148 149 // Returns an array of pointers to |parsed_events_| sorted by sample time. 150 // The first time this is called, it will create the sorted array. 151 const std::vector<ParsedEvent*>& GetEventsSortedByTime() const { 152 return parsed_events_sorted_by_time_; 153 } 154 155 const PerfEventStats& stats() const { 156 return stats_; 157 } 158 159 protected: 160 // Defines a type for a pid:tid pair. 161 typedef std::pair<uint32_t, uint32_t> PidTid; 162 163 // Sort |parsed_events_| by time, storing the results in 164 // |parsed_events_sorted_by_time_|. 165 // Events can not be sorted by time if PERF_SAMPLE_TIME is not set in 166 // attr.sample_type (PerfReader.sample_type_). In that case, 167 // |parsed_events_sorted_by_time_| is not actually sorted, but has the same 168 // order as |parsed_events_|. 169 void MaybeSortParsedEvents(); 170 171 // Used for processing events. e.g. remapping with synthetic addresses. 172 bool ProcessEvents(); 173 template <typename MMapEventT> 174 bool MapMmapEvent(MMapEventT* event, uint64_t id) { 175 return MapMmapEvent(id, 176 event->pid, 177 &event->start, 178 &event->len, 179 &event->pgoff); 180 } 181 bool MapMmapEvent(uint64_t id, 182 uint32_t pid, 183 uint64_t* p_start, 184 uint64_t* p_len, 185 uint64_t* p_pgoff); 186 bool MapForkEvent(const struct fork_event& event); 187 bool MapCommEvent(const struct comm_event& event); 188 189 // Does a sample event remap and then returns DSO name and offset of sample. 190 bool MapSampleEvent(ParsedEvent* parsed_event); 191 192 std::vector<ParsedEvent> parsed_events_; 193 // See MaybeSortParsedEvents to see why this might not actually be sorted 194 // by time: 195 std::vector<ParsedEvent*> parsed_events_sorted_by_time_; 196 197 Options options_; // Store all option flags as one struct. 198 199 // Maps pid/tid to commands. 200 std::map<PidTid, const string*> pidtid_to_comm_map_; 201 202 // A set to store the actual command strings. 203 std::set<string> commands_; 204 205 PerfEventStats stats_; 206 207 // A set of unique DSOs that may be referenced by multiple events. 208 std::set<DSOInfo> dso_set_; 209 210 private: 211 // Calls MapIPAndPidAndGetNameAndOffset() on the callchain of a sample event. 212 bool MapCallchain(const uint64_t ip, 213 const uint32_t pid, 214 uint64_t original_event_addr, 215 struct ip_callchain* callchain, 216 ParsedEvent* parsed_event); 217 218 // Trims the branch stack for null entries and calls 219 // MapIPAndPidAndGetNameAndOffset() on each entry. 220 bool MapBranchStack(const uint32_t pid, 221 struct branch_stack* branch_stack, 222 ParsedEvent* parsed_event); 223 224 // This maps a sample event and returns the mapped address, DSO name, and 225 // offset within the DSO. This is a private function because the API might 226 // change in the future, and we don't want derived classes to be stuck with an 227 // obsolete API. 228 bool MapIPAndPidAndGetNameAndOffset( 229 uint64_t ip, 230 uint32_t pid, 231 uint64_t* new_ip, 232 ParsedEvent::DSOAndOffset* dso_and_offset); 233 234 // Create a process mapper for a process. Optionally pass in a parent pid 235 // |ppid| from which to copy mappings. 236 // Returns (mapper, true) if a new AddressMapper was created, and 237 // (mapper, false) if there is an existing mapper. 238 std::pair<AddressMapper*, bool> GetOrCreateProcessMapper(uint32_t pid, 239 uint32_t *ppid = NULL); 240 241 std::unique_ptr<AddressMapper> kernel_mapper_; 242 std::map<uint32_t, std::unique_ptr<AddressMapper>> process_mappers_; 243 244 DISALLOW_COPY_AND_ASSIGN(PerfParser); 245}; 246 247} // namespace quipper 248 249#endif // CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_ 250