1/*
2 * Copyright (c) 2016, Google Inc.
3 * All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef PERFTOOLS_PERF_DATA_HANDLER_H_
9#define PERFTOOLS_PERF_DATA_HANDLER_H_
10
11#include <vector>
12
13#include "int_compat.h"
14#include "string_compat.h"
15#include "quipper/perf_data.pb.h"
16
17namespace perftools {
18
19// PerfDataHandler defines an interface for processing PerfDataProto
20// with normalized sample fields (i.e., materializing mappings,
21// filenames, and build-ids).
22//
23// To use, subclass PerfDataHandler and implement the required
24// methods, then call Process() and handler will be called for every
25// SAMPLE event.
26//
27// Context events' pointers to Mappings will be constant for the lifetime of a
28// process, so subclasses may use the pointer values as a key to various caches
29// they may want to maintain as part of the output data creation.
30class PerfDataHandler {
31 public:
32  struct Mapping {
33   public:
34    Mapping(const string* filename, const string* build_id, uint64 start,
35            uint64 limit, uint64 file_offset, uint64 filename_md5_prefix)
36        : filename(filename),
37          build_id(build_id),
38          start(start),
39          limit(limit),
40          file_offset(file_offset),
41          filename_md5_prefix(filename_md5_prefix) {}
42
43    // filename and build_id are pointers into the provided
44    // PerfDataProto and may be nullptr.
45    const string* filename;
46    const string* build_id;
47    uint64 start;
48    uint64 limit;  // limit=ceiling.
49    uint64 file_offset;
50    uint64 filename_md5_prefix;
51
52   private:
53    Mapping() {}
54  };
55
56  struct Location {
57    Location() : ip(0), mapping(nullptr) {}
58
59    uint64 ip;
60    const Mapping* mapping;
61  };
62
63  struct BranchStackPair {
64    BranchStackPair() : mispredicted(false) {}
65
66    Location from;
67    Location to;
68    bool mispredicted;
69  };
70
71  struct SampleContext {
72    SampleContext(const quipper::PerfDataProto::EventHeader &h,
73                  const quipper::PerfDataProto::SampleEvent &s)
74        : header(h),
75          sample(s),
76          main_mapping(nullptr),
77          sample_mapping(nullptr),
78          file_attrs_index(-1) {}
79
80    // The event's header.
81    const quipper::PerfDataProto::EventHeader &header;
82    // An event.
83    const quipper::PerfDataProto::SampleEvent &sample;
84    // The mapping for the main binary for this program.
85    const Mapping* main_mapping;
86    // The mapping in which event.ip is found.
87    const Mapping* sample_mapping;
88    // Locations corresponding to event.callchain.
89    std::vector<Location> callchain;
90    // Locations corresponding to entries in event.branch_stack.
91    std::vector<BranchStackPair> branch_stack;
92    // An index into PerfDataProto.file_attrs or -1 if
93    // unavailable.
94    int64 file_attrs_index;
95  };
96
97  struct CommContext {
98    // A comm event.
99    const quipper::PerfDataProto::CommEvent* comm;
100  };
101
102  struct MMapContext {
103    // A memory mapping to be passed to the subclass. Should be the same mapping
104    // that gets added to pid_to_mmaps_.
105    const PerfDataHandler::Mapping* mapping;
106    // The process id used as a key to pid_to_mmaps_.
107    uint32 pid;
108  };
109
110  PerfDataHandler(const PerfDataHandler&) = delete;
111  PerfDataHandler& operator=(const PerfDataHandler&) = delete;
112
113  // Process initiates processing of perf_proto.  handler.Sample will
114  // be called for every event in the profile.
115  static void Process(const quipper::PerfDataProto& perf_data,
116                      PerfDataHandler* handler);
117
118  virtual ~PerfDataHandler() {}
119
120  // Implement these callbacks:
121  // Called for every sample.
122  virtual void Sample(const SampleContext& sample) = 0;
123  // When comm.pid()==comm.tid() it indicates an exec() happened.
124  virtual void Comm(const CommContext& comm) = 0;
125  // Called for every mmap event.
126  virtual void MMap(const MMapContext& mmap) = 0;
127
128 protected:
129  PerfDataHandler();
130};
131
132}  // namespace perftools
133
134#endif  // PERFTOOLS_PERF_DATA_HANDLER_H_
135