249 lines
7.5 KiB
C++
249 lines
7.5 KiB
C++
// 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_
|