// 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.

#include "chromiumos-wide-profiling/perf_parser.h"

#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <memory>
#include <set>
#include <sstream>

#include "base/logging.h"

#include "chromiumos-wide-profiling/address_mapper.h"
#include "chromiumos-wide-profiling/compat/proto.h"
#include "chromiumos-wide-profiling/compat/string.h"
#include "chromiumos-wide-profiling/dso.h"
#include "chromiumos-wide-profiling/huge_pages_mapping_deducer.h"
#include "chromiumos-wide-profiling/utils.h"

namespace quipper {

using BranchStackEntry = PerfDataProto_BranchStackEntry;
using CommEvent = PerfDataProto_CommEvent;
using ForkEvent = PerfDataProto_ForkEvent;
using MMapEvent = PerfDataProto_MMapEvent;
using PerfEvent = PerfDataProto_PerfEvent;
using SampleEvent = PerfDataProto_SampleEvent;

namespace {

// MMAPs are aligned to pages of this many bytes.
const uint64_t kMmapPageAlignment = sysconf(_SC_PAGESIZE);

// Name and ID of the kernel swapper process.
const char kSwapperCommandName[] = "swapper";
const uint32_t kSwapperPid = 0;

// Name of Chrome binary.
const char kChromeFilename[] = "/opt/google/chrome/chrome";

// Returns the offset within a page of size |kMmapPageAlignment|, given an
// address. Requires that |kMmapPageAlignment| be a power of 2.
uint64_t GetPageAlignedOffset(uint64_t addr) {
  return addr % kMmapPageAlignment;
}

// Returns true if |e1| has an earlier timestamp than |e2|. Used to sort an
// array of events.
bool CompareParsedEventTimes(const ParsedEvent& e1, const ParsedEvent& e2) {
  return (GetTimeFromPerfEvent(*e1.event_ptr) <
          GetTimeFromPerfEvent(*e2.event_ptr));
}

bool IsNullBranchStackEntry(const BranchStackEntry& entry) {
  return (!entry.from_ip() && !entry.to_ip());
}

// Walks through all the perf events in |*reader| and searches for split
// mappings due to huge pages. Combines these split mappings into one and
// replaces the split mapping events. Modifies the events vector stored in
// |*reader|.
//
// This may not correctly handle perf data that has been processed to remove
// MMAPs that contain no sample events, since one or more of the mappings
// necessary to resolve the huge pages mapping could have been discarded. The
// result would be that the huge pages mapping would remain as "//anon" and the
// other mappings would remain unchanged.
void CombineHugePagesMappings(PerfReader* reader) {
    std::map<uint32_t, std::unique_ptr<HugePagesMappingDeducer>>
        pids_to_deducers;
    RepeatedPtrField<PerfEvent> new_events;
    new_events.Reserve(reader->events().size());

    for (int i = 0; i < reader->events().size(); ++i) {
      PerfEvent* event = reader->mutable_events()->Mutable(i);
      if (!event->has_mmap_event()) {
        new_events.Add()->Swap(event);
        continue;
      }

      const MMapEvent& mmap = event->mmap_event();
      // Create a new huge pages mapping deducer for the process if necessary.
      auto& deducer = pids_to_deducers[mmap.pid()];
      if (!deducer) {
        deducer.reset(new HugePagesMappingDeducer(kChromeFilename));
      }
      deducer->ProcessMmap(mmap);
      if (!deducer->CombinedMappingAvailable()) {
        new_events.Add()->Swap(event);
        continue;
      }

      // When there is a newly combined mapping, walk backwards to find the
      // existing mappings and replace them with the combined mapping. Assumes
      // that within the events vector, the split Chrome mappings appear
      // consecutively, with no other mappings in between.
      const MMapEvent& combined_mmap = deducer->combined_mapping();
      for (int j = new_events.size() - 1;
           j >= 0 && new_events.Get(j).has_mmap_event();
           --j) {
        MMapEvent* old_mmap = new_events.Mutable(j)->mutable_mmap_event();
        if (old_mmap->start() == combined_mmap.start()) {
          // Delete all split mappings except the first one...
          new_events.DeleteSubrange(j + 1, new_events.size() - j - 1);
          // ... and update it with the new combined mapping info.
          *old_mmap = combined_mmap;
          break;
        }
      }
    }

    reader->mutable_events()->Swap(&new_events);
}

}  // namespace

PerfParser::PerfParser(PerfReader* reader) : reader_(reader) {}

PerfParser::~PerfParser() {}

PerfParser::PerfParser(PerfReader* reader, const PerfParserOptions& options)
    : reader_(reader),
      options_(options) {}

bool PerfParser::ParseRawEvents() {
  // Just in case there was data from a previous call.
  process_mappers_.clear();

  // Find and combine split huge pages mappings.
  if (options_.combine_huge_pages_mappings) {
    CombineHugePagesMappings(reader_);
  }

  // Clear the parsed events to reset their fields. Otherwise, non-sample events
  // may have residual DSO+offset info.
  parsed_events_.clear();

  // Events of type PERF_RECORD_FINISHED_ROUND don't have a timestamp, and are
  // not needed.
  // TODO(dhsharp): Follow the pattern of perf's util/ordered_events to
  // use the partial-sorting of events between rounds to sort faster.
  parsed_events_.resize(reader_->events().size());
  size_t write_index = 0;
  for (int i = 0; i < reader_->events().size(); ++i) {
    if (reader_->events().Get(i).header().type() == PERF_RECORD_FINISHED_ROUND)
      continue;
    parsed_events_[write_index++].event_ptr =
        reader_->mutable_events()->Mutable(i);
  }
  parsed_events_.resize(write_index);

  MaybeSortParsedEvents();
  ProcessEvents();

  if (!options_.discard_unused_events)
    return true;

  // Some MMAP/MMAP2 events' mapped regions will not have any samples. These
  // MMAP/MMAP2 events should be dropped. |parsed_events_| should be
  // reconstructed without these events.
  write_index = 0;
  size_t read_index;
  for (read_index = 0; read_index < parsed_events_.size(); ++read_index) {
    const ParsedEvent& event = parsed_events_[read_index];
    if (event.event_ptr->has_mmap_event() &&
        event.num_samples_in_mmap_region == 0) {
      continue;
    }
    if (read_index != write_index)
      parsed_events_[write_index] = event;
    ++write_index;
  }
  CHECK_LE(write_index, parsed_events_.size());
  parsed_events_.resize(write_index);

  // Update the events in |reader_| to match the updated events.
  UpdatePerfEventsFromParsedEvents();

  return true;
}

bool PerfParser::ProcessEvents() {
  stats_ = {0};

  stats_.did_remap = false;   // Explicitly clear the remap flag.

  // Pid 0 is called the swapper process. Even though perf does not record a
  // COMM event for pid 0, we act like we did receive a COMM event for it. Perf
  // does this itself, example:
  //   http://lxr.free-electrons.com/source/tools/perf/util/session.c#L1120
  commands_.insert(kSwapperCommandName);
  pidtid_to_comm_map_[std::make_pair(kSwapperPid, kSwapperPid)] =
      &(*commands_.find(kSwapperCommandName));

  // NB: Not necessarily actually sorted by time.
  for (size_t i = 0; i < parsed_events_.size(); ++i) {
    ParsedEvent& parsed_event = parsed_events_[i];
    PerfEvent& event = *parsed_event.event_ptr;
    switch (event.header().type()) {
      case PERF_RECORD_SAMPLE:
        // SAMPLE doesn't have any fields to log at a fixed,
        // previously-endian-swapped location. This used to log ip.
        VLOG(1) << "SAMPLE";
        ++stats_.num_sample_events;
        if (MapSampleEvent(&parsed_event))
          ++stats_.num_sample_events_mapped;
        break;
      case PERF_RECORD_MMAP:
      case PERF_RECORD_MMAP2:
      {
        const char* mmap_type_name =
            event.header().type() == PERF_RECORD_MMAP ? "MMAP" : "MMAP2";
        VLOG(1) << mmap_type_name << ": " << event.mmap_event().filename();
        ++stats_.num_mmap_events;
        // Use the array index of the current mmap event as a unique identifier.
        CHECK(MapMmapEvent(event.mutable_mmap_event(), i))
            << "Unable to map " << mmap_type_name << " event!";
        // No samples in this MMAP region yet, hopefully.
        parsed_event.num_samples_in_mmap_region = 0;
        DSOInfo dso_info;
        dso_info.name = event.mmap_event().filename();
        if (event.header().type() == PERF_RECORD_MMAP2) {
          dso_info.maj = event.mmap_event().maj();
          dso_info.min = event.mmap_event().min();
          dso_info.ino = event.mmap_event().ino();
        }
        name_to_dso_.emplace(dso_info.name, dso_info);
        break;
      }
      case PERF_RECORD_FORK:
        VLOG(1) << "FORK: " << event.fork_event().ppid()
                << ":" << event.fork_event().ptid()
                << " -> " << event.fork_event().pid()
                << ":" << event.fork_event().tid();
        ++stats_.num_fork_events;
        CHECK(MapForkEvent(event.fork_event())) << "Unable to map FORK event!";
        break;
      case PERF_RECORD_EXIT:
        // EXIT events have the same structure as FORK events.
        VLOG(1) << "EXIT: " << event.fork_event().ppid()
                << ":" << event.fork_event().ptid();
        ++stats_.num_exit_events;
        break;
      case PERF_RECORD_COMM:
      {
        VLOG(1) << "COMM: " << event.comm_event().pid()
                << ":" << event.comm_event().tid() << ": "
                << event.comm_event().comm();
        ++stats_.num_comm_events;
        CHECK(MapCommEvent(event.comm_event()));
        commands_.insert(event.comm_event().comm());
        const PidTid pidtid = std::make_pair(event.comm_event().pid(),
                                             event.comm_event().tid());
        pidtid_to_comm_map_[pidtid] =
            &(*commands_.find(event.comm_event().comm()));
        break;
      }
      case PERF_RECORD_LOST:
      case PERF_RECORD_THROTTLE:
      case PERF_RECORD_UNTHROTTLE:
      case PERF_RECORD_READ:
      case PERF_RECORD_MAX:
        VLOG(1) << "Parsed event type: " << event.header().type()
                << ". Doing nothing.";
        break;
      default:
        LOG(ERROR) << "Unknown event type: " << event.header().type();
        return false;
    }
  }
  if (!FillInDsoBuildIds())
    return false;

  // Print stats collected from parsing.
  LOG(INFO) << "Parser processed: "
            << stats_.num_mmap_events << " MMAP/MMAP2 events, "
            << stats_.num_comm_events << " COMM events, "
            << stats_.num_fork_events << " FORK events, "
            << stats_.num_exit_events << " EXIT events, "
            << stats_.num_sample_events << " SAMPLE events, "
            << stats_.num_sample_events_mapped << " of these were mapped";

  float sample_mapping_percentage =
      static_cast<float>(stats_.num_sample_events_mapped) /
      stats_.num_sample_events * 100.;
  float threshold = options_.sample_mapping_percentage_threshold;
  if (sample_mapping_percentage < threshold) {
    LOG(ERROR) << "Mapped " << static_cast<int>(sample_mapping_percentage)
               << "% of samples, expected at least "
               << static_cast<int>(threshold) << "%";
    return false;
  }
  stats_.did_remap = options_.do_remap;
  return true;
}

namespace {

class FdCloser {
 public:
  explicit FdCloser(int fd) : fd_(fd) {}
  ~FdCloser() { if (fd_ != -1) close(fd_); }
 private:
  FdCloser() = delete;
  FdCloser(FdCloser&) = delete;

  int fd_;
};

bool ReadElfBuildIdIfSameInode(const string& dso_path, const DSOInfo& dso,
                               string* buildid) {
  int fd = open(dso_path.c_str(), O_RDONLY);
  FdCloser fd_closer(fd);
  if (fd == -1) {
    if (errno != ENOENT)
      LOG(ERROR) << "Failed to open ELF file: " << dso_path;
    return false;
  }

  struct stat s;
  CHECK_GE(fstat(fd, &s), 0);
  // Only reject based on inode if we actually have device info (from MMAP2).
  if (dso.maj != 0 && dso.min != 0 && !SameInode(dso, &s))
    return false;

  return ReadElfBuildId(fd, buildid);
}

// Looks up build ID of a given DSO by reading directly from the file system.
// - Does not support reading build ID of the main kernel binary.
// - Reads build IDs of kernel modules and other DSOs using functions in dso.h.
string FindDsoBuildId(const DSOInfo& dso_info) {
  string buildid_bin;
  const string& dso_name = dso_info.name;
  if (IsKernelNonModuleName(dso_name))
    return buildid_bin;  // still empty
  // Does this look like a kernel module?
  if (dso_name.size() >= 2 && dso_name[0] == '[' && dso_name.back() == ']') {
    // This may not be successful, but either way, just return. buildid_bin
    // will be empty if the module was not found.
    ReadModuleBuildId(dso_name.substr(1, dso_name.size() - 2),
                      &buildid_bin);
    return buildid_bin;
  }
  // Try normal files, possibly inside containers.
  u32 last_pid = 0;
  for (PidTid pidtid : dso_info.threads) {
    u32 pid, tid;
    std::tie(pid, tid) = pidtid;
    stringstream dso_path_stream;
    dso_path_stream << "/proc/" << tid << "/root/" << dso_name;
    string dso_path = dso_path_stream.str();
    if (ReadElfBuildIdIfSameInode(dso_path, dso_info, &buildid_bin)) {
      return buildid_bin;
    }
    // Avoid re-trying the parent process if it's the same for multiple threads.
    // dso_info.threads is sorted, so threads in a process should be adjacent.
    if (pid == last_pid || pid == tid)
      continue;
    last_pid = pid;
    // Try the parent process:
    stringstream parent_dso_path_stream;
    parent_dso_path_stream << "/proc/" << pid << "/root/" << dso_name;
    string parent_dso_path = parent_dso_path_stream.str();
    if (ReadElfBuildIdIfSameInode(parent_dso_path, dso_info, &buildid_bin)) {
      return buildid_bin;
    }
  }
  // Still don't have a buildid. Try our own filesystem:
  if (ReadElfBuildIdIfSameInode(dso_name, dso_info, &buildid_bin)) {
    return buildid_bin;
  }
  return buildid_bin;  // still empty.
}

}  // namespace

bool PerfParser::FillInDsoBuildIds() {
  std::map<string, string> filenames_to_build_ids;
  reader_->GetFilenamesToBuildIDs(&filenames_to_build_ids);

  std::map<string, string> new_buildids;

  for (std::pair<const string, DSOInfo>& kv : name_to_dso_) {
    DSOInfo& dso_info = kv.second;
    const auto it = filenames_to_build_ids.find(dso_info.name);
    if (it != filenames_to_build_ids.end()) {
      dso_info.build_id = it->second;
    }
    // If there is both an existing build ID and a new build ID returned by
    // FindDsoBuildId(), overwrite the existing build ID.
    if (options_.read_missing_buildids && dso_info.hit) {
      string buildid_bin = FindDsoBuildId(dso_info);
      if (!buildid_bin.empty()) {
        dso_info.build_id = RawDataToHexString(buildid_bin);
        new_buildids[dso_info.name] = dso_info.build_id;
      }
    }
  }

  if (new_buildids.empty())
    return true;
  return reader_->InjectBuildIDs(new_buildids);
}

void PerfParser::MaybeSortParsedEvents() {
  if (!options_.sort_events_by_time)
    return;

  bool have_sample_time = true;
  for (const auto& attr : reader_->attrs()) {
    if (!(attr.attr().sample_type() & PERF_SAMPLE_TIME)) {
      have_sample_time = false;
    }
  }
  if (!have_sample_time) {
    return;
  }

  // Sort the events based on timestamp.
  std::stable_sort(parsed_events_.begin(), parsed_events_.end(),
                   CompareParsedEventTimes);

  UpdatePerfEventsFromParsedEvents();
}

void PerfParser::UpdatePerfEventsFromParsedEvents() {
  // Reorder the events in |reader_| to match the order of |parsed_events_|.
  // The |event_ptr|'s in |parsed_events_| are pointers to existing events in
  // |reader_|.
  RepeatedPtrField<PerfEvent> new_events;
  new_events.Reserve(parsed_events_.size());
  for (ParsedEvent& parsed_event : parsed_events_) {
    PerfEvent* new_event = new_events.Add();
    new_event->Swap(parsed_event.event_ptr);
    parsed_event.event_ptr = new_event;
  }

  reader_->mutable_events()->Swap(&new_events);
}

bool PerfParser::MapSampleEvent(ParsedEvent* parsed_event) {
  bool mapping_failed = false;

  const PerfEvent& event = *parsed_event->event_ptr;
  if (!event.has_sample_event() ||
      !(event.sample_event().has_ip() &&
        event.sample_event().has_pid() &&
        event.sample_event().has_tid())) {
    return false;
  }
  SampleEvent& sample_info = *parsed_event->event_ptr->mutable_sample_event();

  // Find the associated command.
  PidTid pidtid = std::make_pair(sample_info.pid(), sample_info.tid());
  const auto comm_iter = pidtid_to_comm_map_.find(pidtid);
  if (comm_iter != pidtid_to_comm_map_.end())
    parsed_event->set_command(comm_iter->second);

  const uint64_t unmapped_event_ip = sample_info.ip();
  uint64_t remapped_event_ip = 0;

  // Map the event IP itself.
  if (!MapIPAndPidAndGetNameAndOffset(sample_info.ip(),
                                      pidtid,
                                      &remapped_event_ip,
                                      &parsed_event->dso_and_offset)) {
    mapping_failed = true;
  } else {
    sample_info.set_ip(remapped_event_ip);
  }

  if (sample_info.callchain_size() &&
      !MapCallchain(sample_info.ip(),
                    pidtid,
                    unmapped_event_ip,
                    sample_info.mutable_callchain(),
                    parsed_event)) {
    mapping_failed = true;
  }

  if (sample_info.branch_stack_size() &&
      !MapBranchStack(pidtid,
                      sample_info.mutable_branch_stack(),
                      parsed_event)) {
    mapping_failed = true;
  }

  return !mapping_failed;
}

bool PerfParser::MapCallchain(const uint64_t ip,
                              const PidTid pidtid,
                              const uint64_t original_event_addr,
                              RepeatedField<uint64>* callchain,
                              ParsedEvent* parsed_event) {
  if (!callchain) {
    LOG(ERROR) << "NULL call stack data.";
    return false;
  }

  bool mapping_failed = false;

  // If the callchain's length is 0, there is no work to do.
  if (callchain->size() == 0)
    return true;

  // Keeps track of whether the current entry is kernel or user.
  parsed_event->callchain.resize(callchain->size());
  int num_entries_mapped = 0;
  for (int i = 0; i < callchain->size(); ++i) {
    uint64_t entry = callchain->Get(i);
    // When a callchain context entry is found, do not attempt to symbolize it.
    if (entry >= PERF_CONTEXT_MAX) {
      continue;
    }
    // The sample address has already been mapped so no need to map it.
    if (entry == original_event_addr) {
      callchain->Set(i, ip);
      continue;
    }
    uint64_t mapped_addr = 0;
    if (!MapIPAndPidAndGetNameAndOffset(
            entry,
            pidtid,
            &mapped_addr,
            &parsed_event->callchain[num_entries_mapped++])) {
      mapping_failed = true;
    } else {
      callchain->Set(i, mapped_addr);
    }
  }
  // Not all the entries were mapped.  Trim |parsed_event->callchain| to
  // remove unused entries at the end.
  parsed_event->callchain.resize(num_entries_mapped);

  return !mapping_failed;
}

bool PerfParser::MapBranchStack(
    const PidTid pidtid,
    RepeatedPtrField<BranchStackEntry>* branch_stack,
    ParsedEvent* parsed_event) {
  if (!branch_stack) {
    LOG(ERROR) << "NULL branch stack data.";
    return false;
  }

  // First, trim the branch stack to remove trailing null entries.
  size_t trimmed_size = 0;
  for (const BranchStackEntry& entry : *branch_stack) {
    // Count the number of non-null entries before the first null entry.
    if (IsNullBranchStackEntry(entry))
      break;
    ++trimmed_size;
  }

  // If a null entry was found, make sure all subsequent null entries are NULL
  // as well.
  for (int i = trimmed_size; i < branch_stack->size(); ++i) {
    const BranchStackEntry& entry = branch_stack->Get(i);
    if (!IsNullBranchStackEntry(entry)) {
      LOG(ERROR) << "Non-null branch stack entry found after null entry: "
                 << reinterpret_cast<void*>(entry.from_ip()) << " -> "
                 << reinterpret_cast<void*>(entry.to_ip());
      return false;
    }
  }

  // Map branch stack addresses.
  parsed_event->branch_stack.resize(trimmed_size);
  for (unsigned int i = 0; i < trimmed_size; ++i) {
    BranchStackEntry* entry = branch_stack->Mutable(i);
    ParsedEvent::BranchEntry& parsed_entry = parsed_event->branch_stack[i];

    uint64_t from_mapped = 0;
    if (!MapIPAndPidAndGetNameAndOffset(entry->from_ip(),
                                        pidtid,
                                        &from_mapped,
                                        &parsed_entry.from)) {
      return false;
    }
    entry->set_from_ip(from_mapped);

    uint64_t to_mapped = 0;
    if (!MapIPAndPidAndGetNameAndOffset(entry->to_ip(),
                                        pidtid,
                                        &to_mapped,
                                        &parsed_entry.to)) {
      return false;
    }
    entry->set_to_ip(to_mapped);

    parsed_entry.predicted = !entry->mispredicted();
  }

  return true;
}

bool PerfParser::MapIPAndPidAndGetNameAndOffset(
    uint64_t ip,
    PidTid pidtid,
    uint64_t* new_ip,
    ParsedEvent::DSOAndOffset* dso_and_offset) {
  DCHECK(dso_and_offset);
  // Attempt to find the synthetic address of the IP sample in this order:
  // 1. Address space of the kernel.
  // 2. Address space of its own process.
  // 3. Address space of the parent process.

  uint64_t mapped_addr = 0;

  // Sometimes the first event we see is a SAMPLE event and we don't have the
  // time to create an address mapper for a process. Example, for pid 0.
  AddressMapper* mapper = GetOrCreateProcessMapper(pidtid.first).first;
  bool mapped = mapper->GetMappedAddress(ip, &mapped_addr);
  // TODO(asharif): What should we do when we cannot map a SAMPLE event?

  if (mapped) {
    uint64_t id = UINT64_MAX;
    CHECK(mapper->GetMappedIDAndOffset(ip, &id, &dso_and_offset->offset_));
    // Make sure the ID points to a valid event.
    CHECK_LE(id, parsed_events_.size());
    ParsedEvent& parsed_event = parsed_events_[id];
    const auto& event = parsed_event.event_ptr;
    DCHECK(event->has_mmap_event()) << "Expected MMAP or MMAP2 event";

    // Find the mmap DSO filename in the set of known DSO names.
    auto dso_iter = name_to_dso_.find(event->mmap_event().filename());
    CHECK(dso_iter != name_to_dso_.end());
    dso_and_offset->dso_info_ = &dso_iter->second;

    dso_iter->second.hit = true;
    dso_iter->second.threads.insert(pidtid);
    ++parsed_event.num_samples_in_mmap_region;

    if (options_.do_remap) {
      if (GetPageAlignedOffset(mapped_addr) != GetPageAlignedOffset(ip)) {
        LOG(ERROR) << "Remapped address " << std::hex << mapped_addr << " "
                   << "does not have the same page alignment offset as "
                   << "original address " << ip;
        return false;
      }
      *new_ip = mapped_addr;
    } else {
      *new_ip = ip;
    }
  }
  return mapped;
}

bool PerfParser::MapMmapEvent(PerfDataProto_MMapEvent* event, uint64_t id) {
  // We need to hide only the real kernel addresses.  However, to make things
  // more secure, and make the mapping idempotent, we should remap all
  // addresses, both kernel and non-kernel.

  AddressMapper* mapper = GetOrCreateProcessMapper(event->pid()).first;

  uint64_t start = event->start();
  uint64_t len = event->len();
  uint64_t pgoff = event->pgoff();

  // |id| == 0 corresponds to the kernel mmap. We have several cases here:
  //
  // For ARM and x86, in sudo mode, pgoff == start, example:
  // start=0x80008200
  // pgoff=0x80008200
  // len  =0xfffffff7ff7dff
  //
  // For x86-64, in sudo mode, pgoff is between start and start + len. SAMPLE
  // events lie between pgoff and pgoff + length of the real kernel binary,
  // example:
  // start=0x3bc00000
  // pgoff=0xffffffffbcc00198
  // len  =0xffffffff843fffff
  // SAMPLE events will be found after pgoff. For kernels with ASLR, pgoff will
  // be something only visible to the root user, and will be randomized at
  // startup. With |remap| set to true, we should hide pgoff in this case. So we
  // normalize all SAMPLE events relative to pgoff.
  //
  // For non-sudo mode, the kernel will be mapped from 0 to the pointer limit,
  // example:
  // start=0x0
  // pgoff=0x0
  // len  =0xffffffff
  if (id == 0) {
    // If pgoff is between start and len, we normalize the event by setting
    // start to be pgoff just like how it is for ARM and x86. We also set len to
    // be a much smaller number (closer to the real length of the kernel binary)
    // because SAMPLEs are actually only seen between |event->pgoff| and
    // |event->pgoff + kernel text size|.
    if (pgoff > start && pgoff < start + len) {
      len = len + start - pgoff;
      start = pgoff;
    }
    // For kernels with ALSR pgoff is critical information that should not be
    // revealed when |remap| is true.
    pgoff = 0;
  }

  if (!mapper->MapWithID(start, len, id, pgoff, true)) {
    mapper->DumpToLog();
    return false;
  }

  if (options_.do_remap) {
    uint64_t mapped_addr;
    if (!mapper->GetMappedAddress(start, &mapped_addr)) {
      LOG(ERROR) << "Failed to map starting address " << std::hex << start;
      return false;
    }
    if (GetPageAlignedOffset(mapped_addr) != GetPageAlignedOffset(start)) {
      LOG(ERROR) << "Remapped address " << std::hex << mapped_addr << " "
                 << "does not have the same page alignment offset as start "
                 << "address " << start;
      return false;
    }

    event->set_start(mapped_addr);
    event->set_len(len);
    event->set_pgoff(pgoff);
  }
  return true;
}

bool PerfParser::MapCommEvent(const PerfDataProto_CommEvent& event) {
  GetOrCreateProcessMapper(event.pid());
  return true;
}

bool PerfParser::MapForkEvent(const PerfDataProto_ForkEvent& event) {
  PidTid parent = std::make_pair(event.ppid(), event.ptid());
  PidTid child = std::make_pair(event.pid(), event.tid());
  if (parent != child) {
    auto parent_iter = pidtid_to_comm_map_.find(parent);
    if (parent_iter != pidtid_to_comm_map_.end())
      pidtid_to_comm_map_[child] = parent_iter->second;
  }

  const uint32_t pid = event.pid();

  // If the parent and child pids are the same, this is just a new thread
  // within the same process, so don't do anything.
  if (event.ppid() == pid)
    return true;

  if (!GetOrCreateProcessMapper(pid, event.ppid()).second) {
    DVLOG(1) << "Found an existing process mapper with pid: " << pid;
  }

  return true;
}

std::pair<AddressMapper*, bool> PerfParser::GetOrCreateProcessMapper(
    uint32_t pid, uint32_t ppid) {
  const auto& search = process_mappers_.find(pid);
  if (search != process_mappers_.end()) {
    return std::make_pair(search->second.get(), false);
  }

  std::unique_ptr<AddressMapper> mapper;
  const auto& parent_mapper = process_mappers_.find(ppid);
  if (parent_mapper != process_mappers_.end()) {
    mapper.reset(new AddressMapper(*parent_mapper->second));
  } else {
    mapper.reset(new AddressMapper());
    mapper->set_page_alignment(kMmapPageAlignment);
  }

  const auto inserted =
      process_mappers_.insert(search, std::make_pair(pid, std::move(mapper)));
  return std::make_pair(inserted->second.get(), true);
}

}  // namespace quipper
