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