1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
#define CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
#include <stdint.h>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "perf_reader.h"
#include "perf_utils.h"
namespace quipper {
class AddressMapper;
// A struct containing all relevant info for a mapped DSO, independent of any
// samples.
struct DSOInfo {
string name;
string build_id;
// Comparator that allows this to be stored in a STL set.
bool operator<(const DSOInfo& other) const {
if (name == other.name)
return build_id < other.build_id;
return name < other.name;
}
};
struct ParsedEvent {
// TODO(sque): Turn this struct into a class to privatize member variables.
ParsedEvent() : command_(NULL) {}
// Stores address of an event_t owned by the |PerfReader::events_| vector.
event_t* raw_event;
// For mmap events, use this to count the number of samples that are in this
// region.
uint32_t num_samples_in_mmap_region;
// Command associated with this sample.
const string* command_;
// Accessor for command string.
const string command() const {
if (command_)
return *command_;
return string();
}
void set_command(const string* command) {
command_ = command;
}
// A struct that contains a DSO + offset pair.
struct DSOAndOffset {
const DSOInfo* dso_info_;
uint64_t offset_;
// Accessor methods.
const string dso_name() const {
if (dso_info_)
return dso_info_->name;
return string();
}
const string build_id() const {
if (dso_info_)
return dso_info_->build_id;
return string();
}
uint64_t offset() const {
return offset_;
}
DSOAndOffset() : dso_info_(NULL),
offset_(0) {}
} dso_and_offset;
// DSO+offset info for callchain.
std::vector<DSOAndOffset> callchain;
// DSO + offset info for branch stack entries.
struct BranchEntry {
bool predicted;
DSOAndOffset from;
DSOAndOffset to;
};
std::vector<BranchEntry> branch_stack;
};
struct PerfEventStats {
// Number of each type of event.
uint32_t num_sample_events;
uint32_t num_mmap_events;
uint32_t num_comm_events;
uint32_t num_fork_events;
uint32_t num_exit_events;
// Number of sample events that were successfully mapped using the address
// mapper. The mapping is recorded regardless of whether the address in the
// perf sample event itself was assigned the remapped address. The latter is
// indicated by |did_remap|.
uint32_t num_sample_events_mapped;
// Whether address remapping was enabled during event parsing.
bool did_remap;
};
class PerfParser : public PerfReader {
public:
PerfParser();
~PerfParser();
struct Options {
// For synthetic address mapping.
bool do_remap = false;
// Set this flag to discard non-sample events that don't have any associated
// sample events. e.g. MMAP regions with no samples in them.
bool discard_unused_events = false;
// When mapping perf sample events, at least this percentage of them must be
// successfully mapped in order for ProcessEvents() to return true.
// By default, most samples must be properly mapped in order for sample
// mapping to be considered successful.
float sample_mapping_percentage_threshold = 95.0f;
};
// Constructor that takes in options at PerfParser creation time.
explicit PerfParser(const Options& options);
// Pass in a struct containing various options.
void set_options(const Options& options);
// Gets parsed event/sample info from raw event data.
bool ParseRawEvents();
const std::vector<ParsedEvent>& parsed_events() const {
return parsed_events_;
}
// Returns an array of pointers to |parsed_events_| sorted by sample time.
// The first time this is called, it will create the sorted array.
const std::vector<ParsedEvent*>& GetEventsSortedByTime() const {
return parsed_events_sorted_by_time_;
}
const PerfEventStats& stats() const {
return stats_;
}
protected:
// Defines a type for a pid:tid pair.
typedef std::pair<uint32_t, uint32_t> PidTid;
// Sort |parsed_events_| by time, storing the results in
// |parsed_events_sorted_by_time_|.
// Events can not be sorted by time if PERF_SAMPLE_TIME is not set in
// attr.sample_type (PerfReader.sample_type_). In that case,
// |parsed_events_sorted_by_time_| is not actually sorted, but has the same
// order as |parsed_events_|.
void MaybeSortParsedEvents();
// Used for processing events. e.g. remapping with synthetic addresses.
bool ProcessEvents();
template <typename MMapEventT>
bool MapMmapEvent(MMapEventT* event, uint64_t id) {
return MapMmapEvent(id,
event->pid,
&event->start,
&event->len,
&event->pgoff);
}
bool MapMmapEvent(uint64_t id,
uint32_t pid,
uint64_t* p_start,
uint64_t* p_len,
uint64_t* p_pgoff);
bool MapForkEvent(const struct fork_event& event);
bool MapCommEvent(const struct comm_event& event);
// Does a sample event remap and then returns DSO name and offset of sample.
bool MapSampleEvent(ParsedEvent* parsed_event);
std::vector<ParsedEvent> parsed_events_;
// See MaybeSortParsedEvents to see why this might not actually be sorted
// by time:
std::vector<ParsedEvent*> parsed_events_sorted_by_time_;
Options options_; // Store all option flags as one struct.
// Maps pid/tid to commands.
std::map<PidTid, const string*> pidtid_to_comm_map_;
// A set to store the actual command strings.
std::set<string> commands_;
PerfEventStats stats_;
// A set of unique DSOs that may be referenced by multiple events.
std::set<DSOInfo> dso_set_;
private:
// Calls MapIPAndPidAndGetNameAndOffset() on the callchain of a sample event.
bool MapCallchain(const uint64_t ip,
const uint32_t pid,
uint64_t original_event_addr,
struct ip_callchain* callchain,
ParsedEvent* parsed_event);
// Trims the branch stack for null entries and calls
// MapIPAndPidAndGetNameAndOffset() on each entry.
bool MapBranchStack(const uint32_t pid,
struct branch_stack* branch_stack,
ParsedEvent* parsed_event);
// This maps a sample event and returns the mapped address, DSO name, and
// offset within the DSO. This is a private function because the API might
// change in the future, and we don't want derived classes to be stuck with an
// obsolete API.
bool MapIPAndPidAndGetNameAndOffset(
uint64_t ip,
uint32_t pid,
uint64_t* new_ip,
ParsedEvent::DSOAndOffset* dso_and_offset);
// Create a process mapper for a process. Optionally pass in a parent pid
// |ppid| from which to copy mappings.
// Returns (mapper, true) if a new AddressMapper was created, and
// (mapper, false) if there is an existing mapper.
std::pair<AddressMapper*, bool> GetOrCreateProcessMapper(uint32_t pid,
uint32_t *ppid = NULL);
std::unique_ptr<AddressMapper> kernel_mapper_;
std::map<uint32_t, std::unique_ptr<AddressMapper>> process_mappers_;
DISALLOW_COPY_AND_ASSIGN(PerfParser);
};
} // namespace quipper
#endif // CHROMIUMOS_WIDE_PROFILING_PERF_PARSER_H_
|