17e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
27e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Use of this source code is governed by a BSD-style license that can be
37e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// found in the LICENSE file.
47e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
57e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_parser.h"
67e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
77e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <algorithm>
87e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <cstdio>
97e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include <set>
107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "base/logging.h"
127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "address_mapper.h"
147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "quipper_string.h"
157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh#include "perf_utils.h"
167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace quipper {
187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshnamespace {
207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstruct EventAndTime {
227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  ParsedEvent* event;
237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t time;
247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh};
257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Returns true if |e1| has an earlier timestamp than |e2|.  The args are const
277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// pointers instead of references because of the way this function is used when
287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// calling std::stable_sort.
297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool CompareParsedEventTimes(const std::unique_ptr<EventAndTime>& e1,
307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                             const std::unique_ptr<EventAndTime>& e2) {
317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (e1->time < e2->time);
327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Kernel MMAP entry pid appears as -1
357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint32_t kKernelPid = UINT32_MAX;
367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh// Name and ID of the kernel swapper process.
387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst char kSwapperCommandName[] = "swapper";
397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshconst uint32_t kSwapperPid = 0;
407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool IsNullBranchStackEntry(const struct branch_entry& entry) {
427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return (!entry.from && !entry.to);
437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace
467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshPerfParser::PerfParser()
487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    : kernel_mapper_(new AddressMapper)
497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{}
507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshPerfParser::~PerfParser() {}
527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshPerfParser::PerfParser(const PerfParser::Options& options) {
547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  options_ = options;
557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfParser::set_options(const PerfParser::Options& options) {
587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  options_ = options;
597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::ParseRawEvents() {
627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  process_mappers_.clear();
637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_events_.resize(events_.size());
647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < events_.size(); ++i) {
657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ParsedEvent& parsed_event = parsed_events_[i];
667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    parsed_event.raw_event = events_[i].get();
677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  MaybeSortParsedEvents();
697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ProcessEvents()) {
707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!options_.discard_unused_events)
747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return true;
757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Some MMAP/MMAP2 events' mapped regions will not have any samples. These
777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // MMAP/MMAP2 events should be dropped. |parsed_events_| should be
787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // reconstructed without these events.
797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t write_index = 0;
807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t read_index;
817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (read_index = 0; read_index < parsed_events_.size(); ++read_index) {
827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const ParsedEvent& event = parsed_events_[read_index];
837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if ((event.raw_event->header.type == PERF_RECORD_MMAP ||
847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh         event.raw_event->header.type == PERF_RECORD_MMAP2) &&
857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        event.num_samples_in_mmap_region == 0) {
867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (read_index != write_index)
897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      parsed_events_[write_index] = event;
907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ++write_index;
917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  CHECK_LE(write_index, parsed_events_.size());
937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_events_.resize(write_index);
947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Now regenerate the sorted event list again.  These are pointers to events
967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // so they must be regenerated after a resize() of the ParsedEvent vector.
977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  MaybeSortParsedEvents();
987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
1007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshvoid PerfParser::MaybeSortParsedEvents() {
1037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!(sample_type_ & PERF_SAMPLE_TIME)) {
1047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    parsed_events_sorted_by_time_.resize(parsed_events_.size());
1057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    for (size_t i = 0; i < parsed_events_.size(); ++i) {
1067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      parsed_events_sorted_by_time_[i] = &parsed_events_[i];
1077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
1087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return;
1097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::vector<std::unique_ptr<EventAndTime>> events_and_times;
1117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  events_and_times.resize(parsed_events_.size());
1127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < parsed_events_.size(); ++i) {
1137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    std::unique_ptr<EventAndTime> event_and_time(new EventAndTime);
1147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Store the timestamp and event pointer in an array.
1167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event_and_time->event = &parsed_events_[i];
1177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    struct perf_sample sample_info;
1197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    PerfSampleCustodian custodian(sample_info);
1207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK(ReadPerfSampleInfo(*parsed_events_[i].raw_event, &sample_info));
1217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event_and_time->time = sample_info.time;
1227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    events_and_times[i] = std::move(event_and_time);
1247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Sort the events based on timestamp, and then populate the sorted event
1267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // vector in sorted order.
1277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::stable_sort(events_and_times.begin(), events_and_times.end(),
1287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                   CompareParsedEventTimes);
1297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_events_sorted_by_time_.resize(events_and_times.size());
1317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (unsigned int i = 0; i < events_and_times.size(); ++i) {
1327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    parsed_events_sorted_by_time_[i] = events_and_times[i]->event;
1337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
1347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
1357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::ProcessEvents() {
1377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  memset(&stats_, 0, sizeof(stats_));
1387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  stats_.did_remap = false;   // Explicitly clear the remap flag.
1407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Pid 0 is called the swapper process. Even though perf does not record a
1427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // COMM event for pid 0, we act like we did receive a COMM event for it. Perf
1437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // does this itself, example:
1447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //   http://lxr.free-electrons.com/source/tools/perf/util/session.c#L1120
1457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  commands_.insert(kSwapperCommandName);
1467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  pidtid_to_comm_map_[std::make_pair(kSwapperPid, kSwapperPid)] =
1477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      &(*commands_.find(kSwapperCommandName));
1487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // NB: Not necessarily actually sorted by time.
1507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (unsigned int i = 0; i < parsed_events_sorted_by_time_.size(); ++i) {
1517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ParsedEvent& parsed_event = *parsed_events_sorted_by_time_[i];
1527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    event_t& event = *parsed_event.raw_event;
1537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    switch (event.header.type) {
1547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_SAMPLE:
1557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // SAMPLE doesn't have any fields to log at a fixed,
1567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // previously-endian-swapped location. This used to log ip.
1577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "SAMPLE";
1587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_sample_events;
1597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
1607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        if (MapSampleEvent(&parsed_event)) {
1617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh          ++stats_.num_sample_events_mapped;
1627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        }
1637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
1647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_MMAP: {
1657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "MMAP: " << event.mmap.filename;
1667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_mmap_events;
1677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // Use the array index of the current mmap event as a unique identifier.
1687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        CHECK(MapMmapEvent(&event.mmap, i)) << "Unable to map MMAP event!";
1697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // No samples in this MMAP region yet, hopefully.
1707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        parsed_event.num_samples_in_mmap_region = 0;
1717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        DSOInfo dso_info;
1727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // TODO(sque): Add Build ID as well.
1737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_info.name = event.mmap.filename;
1747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_set_.insert(dso_info);
1757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
1767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      }
1777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_MMAP2: {
1787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "MMAP2: " << event.mmap2.filename;
1797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_mmap_events;
1807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // Use the array index of the current mmap event as a unique identifier.
1817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        CHECK(MapMmapEvent(&event.mmap2, i)) << "Unable to map MMAP2 event!";
1827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // No samples in this MMAP region yet, hopefully.
1837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        parsed_event.num_samples_in_mmap_region = 0;
1847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        DSOInfo dso_info;
1857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // TODO(sque): Add Build ID as well.
1867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_info.name = event.mmap2.filename;
1877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_set_.insert(dso_info);
1887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
1897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      }
1907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_FORK:
1917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "FORK: " << event.fork.ppid << ":" << event.fork.ptid
1927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                << " -> " << event.fork.pid << ":" << event.fork.tid;
1937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_fork_events;
1947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        CHECK(MapForkEvent(event.fork)) << "Unable to map FORK event!";
1957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
1967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_EXIT:
1977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        // EXIT events have the same structure as FORK events.
1987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "EXIT: " << event.fork.ppid << ":" << event.fork.ptid;
1997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_exit_events;
2007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
2017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_COMM:
2027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "COMM: " << event.comm.pid << ":" << event.comm.tid << ": "
2037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                << event.comm.comm;
2047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        ++stats_.num_comm_events;
2057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        CHECK(MapCommEvent(event.comm));
2067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        commands_.insert(event.comm.comm);
2077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        pidtid_to_comm_map_[std::make_pair(event.comm.pid, event.comm.tid)] =
2087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            &(*commands_.find(event.comm.comm));
2097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
2107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_LOST:
2117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_THROTTLE:
2127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_UNTHROTTLE:
2137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_READ:
2147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      case PERF_RECORD_MAX:
2157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        VLOG(1) << "Parsed event type: " << event.header.type
2167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                << ". Doing nothing.";
2177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        break;
2187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      default:
2197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        LOG(ERROR) << "Unknown event type: " << event.header.type;
2207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        return false;
2217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
2227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Print stats collected from parsing.
2257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  DLOG(INFO) << "Parser processed: "
2267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_mmap_events << " MMAP/MMAP2 events, "
2277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_comm_events << " COMM events, "
2287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_fork_events << " FORK events, "
2297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_exit_events << " EXIT events, "
2307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_sample_events << " SAMPLE events, "
2317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            << stats_.num_sample_events_mapped << " of these were mapped";
2327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  float sample_mapping_percentage =
2347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      static_cast<float>(stats_.num_sample_events_mapped) /
2357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      stats_.num_sample_events * 100.;
2367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  float threshold = options_.sample_mapping_percentage_threshold;
2377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_mapping_percentage < threshold) {
2387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(WARNING) << "Mapped " << static_cast<int>(sample_mapping_percentage)
2397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << "% of samples, expected at least "
2407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh               << static_cast<int>(threshold) << "%";
2417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  stats_.did_remap = options_.do_remap;
2447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
2457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapSampleEvent(ParsedEvent* parsed_event) {
2487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  bool mapping_failed = false;
2497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Find the associated command.
2517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!(sample_type_ & PERF_SAMPLE_IP && sample_type_ & PERF_SAMPLE_TID))
2527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  perf_sample sample_info;
2547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PerfSampleCustodian custodian(sample_info);
2557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!ReadPerfSampleInfo(*parsed_event->raw_event, &sample_info))
2567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PidTid pidtid = std::make_pair(sample_info.pid, sample_info.tid);
2587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const auto comm_iter = pidtid_to_comm_map_.find(pidtid);
2597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (comm_iter != pidtid_to_comm_map_.end()) {
2607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    parsed_event->set_command(comm_iter->second);
2617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const uint64_t unmapped_event_ip = sample_info.ip;
2647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Map the event IP itself.
2667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!MapIPAndPidAndGetNameAndOffset(sample_info.ip,
2677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      sample_info.pid,
2687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      &sample_info.ip,
2697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                      &parsed_event->dso_and_offset)) {
2707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapping_failed = true;
2717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_info.callchain &&
2747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      !MapCallchain(sample_info.ip,
2757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    sample_info.pid,
2767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    unmapped_event_ip,
2777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    sample_info.callchain,
2787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                    parsed_event)) {
2797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapping_failed = true;
2807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (sample_info.branch_stack &&
2837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      !MapBranchStack(sample_info.pid,
2847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                      sample_info.branch_stack,
2857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                      parsed_event)) {
2867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapping_failed = true;
2877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Write the remapped data back to the raw event regardless of whether it was
2907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // entirely successfully remapped.  A single failed remap should not
2917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // invalidate all the other remapped entries.
2927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!WritePerfSampleInfo(sample_info, parsed_event->raw_event)) {
2937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "Failed to write back remapped sample info.";
2947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
2957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
2967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
2977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return !mapping_failed;
2987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
2997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapCallchain(const uint64_t ip,
3017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              const uint32_t pid,
3027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              const uint64_t original_event_addr,
3037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              struct ip_callchain* callchain,
3047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              ParsedEvent* parsed_event) {
3057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!callchain) {
3067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "NULL call stack data.";
3077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
3087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  bool mapping_failed = false;
3117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // If the callchain's length is 0, there is no work to do.
3137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (callchain->nr == 0)
3147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return true;
3157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Keeps track of whether the current entry is kernel or user.
3177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_event->callchain.resize(callchain->nr);
3187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  int num_entries_mapped = 0;
3197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (unsigned int j = 0; j < callchain->nr; ++j) {
3207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t entry = callchain->ips[j];
3217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // When a callchain context entry is found, do not attempt to symbolize it.
3227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (entry >= PERF_CONTEXT_MAX) {
3237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
3247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // The sample address has already been mapped so no need to map it.
3267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (entry == original_event_addr) {
3277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      callchain->ips[j] = ip;
3287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      continue;
3297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!MapIPAndPidAndGetNameAndOffset(
3317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            entry,
3327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            pid,
3337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            &callchain->ips[j],
3347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh            &parsed_event->callchain[num_entries_mapped++])) {
3357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      mapping_failed = true;
3367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Not all the entries were mapped.  Trim |parsed_event->callchain| to
3397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // remove unused entries at the end.
3407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_event->callchain.resize(num_entries_mapped);
3417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return !mapping_failed;
3437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
3447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapBranchStack(const uint32_t pid,
3467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                struct branch_stack* branch_stack,
3477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                ParsedEvent* parsed_event) {
3487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!branch_stack) {
3497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    LOG(ERROR) << "NULL branch stack data.";
3507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
3517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // First, trim the branch stack to remove trailing null entries.
3547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  size_t trimmed_size = 0;
3557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = 0; i < branch_stack->nr; ++i) {
3567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Count the number of non-null entries before the first null entry.
3577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (IsNullBranchStackEntry(branch_stack->entries[i])) {
3587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      break;
3597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ++trimmed_size;
3617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // If a null entry was found, make sure all subsequent null entries are NULL
3647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // as well.
3657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (size_t i = trimmed_size; i < branch_stack->nr; ++i) {
3667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    const struct branch_entry& entry = branch_stack->entries[i];
3677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!IsNullBranchStackEntry(entry)) {
3687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Non-null branch stack entry found after null entry: "
3697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << reinterpret_cast<void*>(entry.from) << " -> "
3707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << reinterpret_cast<void*>(entry.to);
3717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
3727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
3747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
3757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Map branch stack addresses.
3767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  parsed_event->branch_stack.resize(trimmed_size);
3777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  for (unsigned int i = 0; i < trimmed_size; ++i) {
3787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    struct branch_entry& entry = branch_stack->entries[i];
3797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ParsedEvent::BranchEntry& parsed_entry = parsed_event->branch_stack[i];
3807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!MapIPAndPidAndGetNameAndOffset(entry.from,
3817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        pid,
3827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        &entry.from,
3837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        &parsed_entry.from)) {
3847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
3857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (!MapIPAndPidAndGetNameAndOffset(entry.to,
3877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        pid,
3887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        &entry.to,
3897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                                        &parsed_entry.to)) {
3907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
3917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
3927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    parsed_entry.predicted = entry.flags.predicted;
3937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // Either predicted or mispredicted, not both. But don't use a CHECK here,
3947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // just exit gracefully because it's a minor issue.
3957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (entry.flags.predicted == entry.flags.mispred) {
3967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      LOG(ERROR) << "Branch stack entry predicted and mispred flags "
3977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                 << "both have value " << entry.flags.mispred;
3987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      return false;
3997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
4007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
4037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
4047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapIPAndPidAndGetNameAndOffset(
4067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t ip,
4077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t pid,
4087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t* new_ip,
4097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    ParsedEvent::DSOAndOffset* dso_and_offset) {
4107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Attempt to find the synthetic address of the IP sample in this order:
4127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // 1. Address space of its own process.
4137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // 2. Address space of the kernel.
4147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t mapped_addr = 0;
4167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // Sometimes the first event we see is a SAMPLE event and we don't have the
4187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // time to create an address mapper for a process. Example, for pid 0.
4197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  AddressMapper* mapper = GetOrCreateProcessMapper(pid).first;
4207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  bool mapped = mapper->GetMappedAddress(ip, &mapped_addr);
4217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!mapped) {
4227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapper = kernel_mapper_.get();
4237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapped = mapper->GetMappedAddress(ip, &mapped_addr);
4247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // TODO(asharif): What should we do when we cannot map a SAMPLE event?
4277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (mapped) {
4287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (dso_and_offset) {
4297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      uint64_t id = kuint64max;
4307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      CHECK(mapper->GetMappedIDAndOffset(ip, &id, &dso_and_offset->offset_));
4317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Make sure the ID points to a valid event.
4327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      CHECK_LE(id, parsed_events_sorted_by_time_.size());
4337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ParsedEvent* parsed_event = parsed_events_sorted_by_time_[id];
4347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      const event_t* raw_event = parsed_event->raw_event;
4357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      DSOInfo dso_info;
4377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      if (raw_event->header.type == PERF_RECORD_MMAP) {
4387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_info.name = raw_event->mmap.filename;
4397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      } else if (raw_event->header.type == PERF_RECORD_MMAP2) {
4407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        dso_info.name = raw_event->mmap2.filename;
4417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      } else {
4427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh        LOG(FATAL) << "Expected MMAP or MMAP2 event";
4437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      }
4447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // Find the mmap DSO filename in the set of known DSO names.
4467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      // TODO(sque): take build IDs into account.
4477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      std::set<DSOInfo>::const_iterator dso_iter = dso_set_.find(dso_info);
4487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      CHECK(dso_iter != dso_set_.end());
4497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      dso_and_offset->dso_info_ = &(*dso_iter);
4507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      ++parsed_event->num_samples_in_mmap_region;
4527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
4537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (options_.do_remap)
4547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      *new_ip = mapped_addr;
4557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
4567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return mapped;
4577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
4587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapMmapEvent(uint64_t id,
4607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              uint32_t pid,
4617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              uint64_t* p_start,
4627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              uint64_t* p_len,
4637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh                              uint64_t* p_pgoff)
4647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh{
4657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // We need to hide only the real kernel addresses.  However, to make things
4667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // more secure, and make the mapping idempotent, we should remap all
4677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // addresses, both kernel and non-kernel.
4687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  AddressMapper* mapper =
4697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      (pid == kKernelPid ? kernel_mapper_.get() :
4707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh       GetOrCreateProcessMapper(pid).first);
4717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t start = *p_start;
4737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t len = *p_len;
4747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint64_t pgoff = *p_pgoff;
4757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
4767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // |id| == 0 corresponds to the kernel mmap. We have several cases here:
4777e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
4787e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // For ARM and x86, in sudo mode, pgoff == start, example:
4797e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // start=0x80008200
4807e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // pgoff=0x80008200
4817e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // len  =0xfffffff7ff7dff
4827e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
4837e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // For x86-64, in sudo mode, pgoff is between start and start + len. SAMPLE
4847e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // events lie between pgoff and pgoff + length of the real kernel binary,
4857e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // example:
4867e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // start=0x3bc00000
4877e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // pgoff=0xffffffffbcc00198
4887e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // len  =0xffffffff843fffff
4897e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // SAMPLE events will be found after pgoff. For kernels with ASLR, pgoff will
4907e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // be something only visible to the root user, and will be randomized at
4917e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // startup. With |remap| set to true, we should hide pgoff in this case. So we
4927e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // normalize all SAMPLE events relative to pgoff.
4937e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  //
4947e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // For non-sudo mode, the kernel will be mapped from 0 to the pointer limit,
4957e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // example:
4967e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // start=0x0
4977e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // pgoff=0x0
4987e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // len  =0xffffffff
4997e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (id == 0) {
5007e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // If pgoff is between start and len, we normalize the event by setting
5017e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // start to be pgoff just like how it is for ARM and x86. We also set len to
5027e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // be a much smaller number (closer to the real length of the kernel binary)
5037e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // because SAMPLEs are actually only seen between |event->pgoff| and
5047e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // |event->pgoff + kernel text size|.
5057e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    if (pgoff > start && pgoff < start + len) {
5067e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      len = len + start - pgoff;
5077e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      start = pgoff;
5087e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    }
5097e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // For kernels with ALSR pgoff is critical information that should not be
5107e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    // revealed when |remap| is true.
5117e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    pgoff = 0;
5127e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5137e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5147e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!mapper->MapWithID(start, len, id, pgoff, true)) {
5157e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapper->DumpToLog();
5167e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return false;
5177e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5187e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5197e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (options_.do_remap) {
5207e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint64_t mapped_addr;
5217e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    CHECK(mapper->GetMappedAddress(start, &mapped_addr));
5227e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *p_start = mapped_addr;
5237e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *p_len = len;
5247e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    *p_pgoff = pgoff;
5257e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5267e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
5277e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
5287e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5297e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshstd::pair<AddressMapper*, bool> PerfParser::GetOrCreateProcessMapper(
5307e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    uint32_t pid, uint32_t *ppid) {
5317e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const auto& search = process_mappers_.find(pid);
5327e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (search != process_mappers_.end()) {
5337e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return std::make_pair(search->second.get(), false);
5347e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5357e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5367e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  std::unique_ptr<AddressMapper> mapper;
5377e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const auto& parent_mapper = (ppid ? process_mappers_.find(*ppid) : process_mappers_.end());
5387e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (parent_mapper != process_mappers_.end())
5397e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      mapper.reset(new AddressMapper(*parent_mapper->second));
5407e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  else
5417e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    mapper.reset(new AddressMapper());
5427e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5437e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const auto inserted =
5447e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      process_mappers_.insert(search, std::make_pair(pid, std::move(mapper)));
5457e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return std::make_pair(inserted->second.get(), true);
5467e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
5477e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5487e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapCommEvent(const struct comm_event& event) {
5497e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  GetOrCreateProcessMapper(event.pid);
5507e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
5517e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
5527e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5537e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntoshbool PerfParser::MapForkEvent(const struct fork_event& event) {
5547e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PidTid parent = std::make_pair(event.ppid, event.ptid);
5557e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  PidTid child = std::make_pair(event.pid, event.tid);
5567e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (parent != child &&
5577e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh      pidtid_to_comm_map_.find(parent) != pidtid_to_comm_map_.end()) {
5587e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    pidtid_to_comm_map_[child] = pidtid_to_comm_map_[parent];
5597e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5607e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5617e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  const uint32_t pid = event.pid;
5627e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5637e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // If the parent and child pids are the same, this is just a new thread
5647e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  // within the same process, so don't do anything.
5657e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (event.ppid == pid)
5667e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    return true;
5677e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5687e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  uint32_t ppid = event.ppid;
5697e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  if (!GetOrCreateProcessMapper(pid, &ppid).second) {
5707e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh    DLOG(INFO) << "Found an existing process mapper with pid: " << pid;
5717e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  }
5727e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5737e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh  return true;
5747e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}
5757e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh
5767e2f4e9d384d501cf86118ebac4b8de2b86eac53Than McIntosh}  // namespace quipper
577