• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 namespace quipper {
22 
23 class AddressMapper;
24 
25 // A struct containing all relevant info for a mapped DSO, independent of any
26 // samples.
27 struct 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 
39 struct ParsedEvent {
40   // TODO(sque): Turn this struct into a class to privatize member variables.
ParsedEventParsedEvent41   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.
commandParsedEvent54   const string command() const {
55     if (command_)
56       return *command_;
57     return string();
58   }
59 
set_commandParsedEvent60   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.
dso_nameParsedEvent::DSOAndOffset70     const string dso_name() const {
71       if (dso_info_)
72         return dso_info_->name;
73       return string();
74     }
build_idParsedEvent::DSOAndOffset75     const string build_id() const {
76       if (dso_info_)
77         return dso_info_->build_id;
78       return string();
79     }
offsetParsedEvent::DSOAndOffset80     uint64_t offset() const {
81       return offset_;
82     }
83 
DSOAndOffsetParsedEvent::DSOAndOffset84     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 
100 struct 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 
118 class 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 
parsed_events()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.
GetEventsSortedByTime()151   const std::vector<ParsedEvent*>& GetEventsSortedByTime() const {
152     return parsed_events_sorted_by_time_;
153   }
154 
stats()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>
MapMmapEvent(MMapEventT * event,uint64_t id)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