Home | History | Annotate | Download | only in quipper
      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.
     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 
    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 
    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