• 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 <memory>
12 #include <set>
13 #include <string>
14 #include <unordered_map>
15 #include <utility>
16 #include <vector>
17 
18 #include "base/macros.h"
19 
20 #include "binary_data_utils.h"
21 #include "compat/proto.h"
22 #include "compat/string.h"
23 #include "dso.h"
24 #include "perf_reader.h"
25 
26 namespace quipper {
27 
28 using PerfEvent = PerfDataProto_PerfEvent;
29 
30 // PID associated with the kernel mmap event.
31 const uint32_t kKernelPid = static_cast<uint32_t>(-1);
32 
33 class AddressMapper;
34 class PerfDataProto_BranchStackEntry;
35 class PerfDataProto_CommEvent;
36 class PerfDataProto_ForkEvent;
37 class PerfDataProto_MMapEvent;
38 class PerfDataProto_PerfEvent;
39 
40 struct ParsedEvent {
ParsedEventParsedEvent41   ParsedEvent() : command_(NULL) {}
42 
43   // Stores address of the original PerfDataProto_PerfEvent owned by a
44   // PerfReader object.
45   PerfDataProto_PerfEvent* event_ptr;
46 
47   // For mmap events, use this to count the number of samples that are in this
48   // region.
49   uint32_t num_samples_in_mmap_region;
50 
51   // Command associated with this sample.
52   const string* command_;
53 
54   // Accessor for command string.
commandParsedEvent55   const string command() const {
56     if (command_) return *command_;
57     return string();
58   }
59 
set_commandParsedEvent60   void set_command(const string* command) { command_ = command; }
61 
62   // A struct that contains a DSO + offset pair.
63   struct DSOAndOffset {
64     const DSOInfo* dso_info_;
65     uint64_t offset_;
66 
67     // Accessor methods.
dso_nameParsedEvent::DSOAndOffset68     const string dso_name() const {
69       if (dso_info_) return dso_info_->name;
70       return string();
71     }
build_idParsedEvent::DSOAndOffset72     const string build_id() const {
73       if (dso_info_) return dso_info_->build_id;
74       return string();
75     }
offsetParsedEvent::DSOAndOffset76     uint64_t offset() const { return offset_; }
77 
DSOAndOffsetParsedEvent::DSOAndOffset78     DSOAndOffset() : dso_info_(NULL), offset_(0) {}
79 
80     bool operator==(const DSOAndOffset& other) const {
81       return offset_ == other.offset_ &&
82              !dso_name().compare(other.dso_name()) &&
83              !build_id().compare(other.build_id());
84     }
85   } dso_and_offset;
86 
87   // DSO + offset info for callchain.
88   std::vector<DSOAndOffset> callchain;
89 
90   // DSO + offset info for branch stack entries.
91   struct BranchEntry {
92     bool predicted;
93     DSOAndOffset from;
94     DSOAndOffset to;
95 
96     bool operator==(const BranchEntry& other) const {
97       return predicted == other.predicted && from == other.from &&
98              to == other.to;
99     }
100   };
101   std::vector<BranchEntry> branch_stack;
102 
103   // For comparing ParsedEvents.
104   bool operator==(const ParsedEvent& other) const {
105     return dso_and_offset == other.dso_and_offset &&
106            std::equal(callchain.begin(), callchain.end(),
107                       other.callchain.begin()) &&
108            std::equal(branch_stack.begin(), branch_stack.end(),
109                       other.branch_stack.begin());
110   }
111 };
112 
113 struct PerfEventStats {
114   // Number of each type of event.
115   uint32_t num_sample_events;
116   uint32_t num_mmap_events;
117   uint32_t num_comm_events;
118   uint32_t num_fork_events;
119   uint32_t num_exit_events;
120 
121   // Number of sample events that were successfully mapped using the address
122   // mapper.  The mapping is recorded regardless of whether the address in the
123   // perf sample event itself was assigned the remapped address.  The latter is
124   // indicated by |did_remap|.
125   uint32_t num_sample_events_mapped;
126 
127   // Whether address remapping was enabled during event parsing.
128   bool did_remap;
129 };
130 
131 struct PerfParserOptions {
132   // For synthetic address mapping.
133   bool do_remap = false;
134   // Set this flag to discard non-sample events that don't have any associated
135   // sample events. e.g. MMAP regions with no samples in them.
136   bool discard_unused_events = false;
137   // When mapping perf sample events, at least this percentage of them must be
138   // successfully mapped in order for ProcessEvents() to return true.
139   // By default, most samples must be properly mapped in order for sample
140   // mapping to be considered successful.
141   float sample_mapping_percentage_threshold = 95.0f;
142   // Set this to sort perf events by time, assuming they have timestamps.
143   // PerfSerializer::serialize_sorted_events_, which is used by
144   // PerfSerializerTest. However, we should look at restructuring PerfParser not
145   // to need it, while still providing some PerfParserStats.
146   bool sort_events_by_time = true;
147   // If buildids are missing from the input data, they can be retrieved from
148   // the filesystem.
149   bool read_missing_buildids = false;
150   // Deduces file names and offsets for hugepage-backed mappings, as
151   // hugepage_text replaces these with anonymous mappings without filename or
152   // offset information..
153   bool deduce_huge_page_mappings = true;
154   // Checks for split binary mappings and merges them when possible.  This
155   // combines the split mappings into a single mapping so future consumers of
156   // the perf data will see  a single mapping and not two or more distinct
157   // mappings.
158   bool combine_mappings = true;
159 };
160 
161 class PerfParser {
162  public:
163   explicit PerfParser(PerfReader* reader);
164   ~PerfParser();
165 
166   // Constructor that takes in options at PerfParser creation time.
167   explicit PerfParser(PerfReader* reader, const PerfParserOptions& options);
168 
169   // Pass in a struct containing various options.
set_options(const PerfParserOptions & options)170   void set_options(const PerfParserOptions& options) { options_ = options; }
171 
172   // Gets parsed event/sample info from raw event data. Stores pointers to the
173   // raw events in an array of ParsedEvents. Does not own the raw events. It is
174   // up to the user of this class to keep track of when these event pointers are
175   // invalidated.
176   bool ParseRawEvents();
177 
parsed_events()178   const std::vector<ParsedEvent>& parsed_events() const {
179     return parsed_events_;
180   }
181 
stats()182   const PerfEventStats& stats() const { return stats_; }
183 
184   // Use with caution. Deserialization uses this to restore stats from proto.
mutable_stats()185   PerfEventStats* mutable_stats() { return &stats_; }
186 
187  private:
188   // Used for processing events.  e.g. remapping with synthetic addresses.
189   bool ProcessEvents();
190 
191   // Used for processing user events.
192   bool ProcessUserEvents(PerfEvent& event);
193 
194   // Looks up build IDs for all DSOs present in |reader_| by direct lookup using
195   // functions in dso.h. If there is a DSO with both an existing build ID and a
196   // new build ID read using dso.h, this will overwrite the existing build ID.
197   bool FillInDsoBuildIds();
198 
199   // Updates |reader_->events| based on the contents of |parsed_events_|. For
200   // example, if |parsed_events_| had some events removed or reordered,
201   // |reader_| would be updated to contain the new sequence of events.
202   void UpdatePerfEventsFromParsedEvents();
203 
204   // Does a sample event remap and then returns DSO name and offset of sample.
205   bool MapSampleEvent(ParsedEvent* parsed_event);
206 
207   // Calls MapIPAndPidAndGetNameAndOffset() on the callchain of a sample event.
208   bool MapCallchain(const uint64_t ip, const PidTid pidtid,
209                     uint64_t original_event_addr,
210                     RepeatedField<uint64>* callchain,
211                     ParsedEvent* parsed_event);
212 
213   // Trims the branch stack for null entries and calls
214   // MapIPAndPidAndGetNameAndOffset() on each entry.
215   bool MapBranchStack(
216       const PidTid pidtid,
217       RepeatedPtrField<PerfDataProto_BranchStackEntry>* branch_stack,
218       ParsedEvent* parsed_event);
219 
220   // This maps a sample event and returns the mapped address, DSO name, and
221   // offset within the DSO.  This is a private function because the API might
222   // change in the future, and we don't want derived classes to be stuck with an
223   // obsolete API.
224   bool MapIPAndPidAndGetNameAndOffset(
225       uint64_t ip, const PidTid pidtid, uint64_t* new_ip,
226       ParsedEvent::DSOAndOffset* dso_and_offset);
227 
228   // Parses a MMAP event. Adds the mapping to the AddressMapper of the event's
229   // process. If |options_.do_remap| is set, will update |event| with the
230   // remapped address.
231   bool MapMmapEvent(PerfDataProto_MMapEvent* event, uint64_t id);
232 
233   // Processes a COMM event. Creates a new AddressMapper for the new command's
234   // process.
235   bool MapCommEvent(const PerfDataProto_CommEvent& event);
236 
237   // Processes a FORK event. Creates a new AddressMapper for the PID of the new
238   // process, if none already exists.
239   bool MapForkEvent(const PerfDataProto_ForkEvent& event);
240 
241   // Create a process mapper for a process. Optionally pass in a parent pid
242   // |ppid| from which to copy mappings.
243   // Returns (mapper, true) if a new AddressMapper was created, and
244   // (mapper, false) if there is an existing mapper.
245   std::pair<AddressMapper*, bool> GetOrCreateProcessMapper(
246       uint32_t pid, uint32_t ppid = kKernelPid);
247 
248   // Points to a PerfReader that contains the input perf data to parse.
249   PerfReader* const reader_;
250 
251   // Stores the output of ParseRawEvents(). Contains DSO + offset info for each
252   // event.
253   std::vector<ParsedEvent> parsed_events_;
254 
255   // Store all option flags as one struct.
256   PerfParserOptions options_;
257 
258   // Maps pid/tid to commands.
259   std::map<PidTid, const string*> pidtid_to_comm_map_;
260 
261   // A set to store the actual command strings.
262   std::set<string> commands_;
263 
264   // ParseRawEvents() records some statistics here.
265   PerfEventStats stats_;
266 
267   // A set of unique DSOs that may be referenced by multiple events.
268   std::unordered_map<string, DSOInfo> name_to_dso_;
269 
270   // Maps process ID to an address mapper for that process.
271   std::unordered_map<uint32_t, std::unique_ptr<AddressMapper>> process_mappers_;
272 
273   DISALLOW_COPY_AND_ASSIGN(PerfParser);
274 };
275 
276 }  // namespace quipper
277 
278 #endif  // CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
279