// Copyright (c) 2012 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_reader.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include <algorithm>
#include <vector>

#include "base/logging.h"
#include "base/macros.h"

#include "chromiumos-wide-profiling/binary_data_utils.h"
#include "chromiumos-wide-profiling/buffer_reader.h"
#include "chromiumos-wide-profiling/buffer_writer.h"
#include "chromiumos-wide-profiling/compat/string.h"
#include "chromiumos-wide-profiling/file_reader.h"
#include "chromiumos-wide-profiling/file_utils.h"
#include "chromiumos-wide-profiling/perf_data_structures.h"
#include "chromiumos-wide-profiling/perf_data_utils.h"
#include "chromiumos-wide-profiling/sample_info_reader.h"

namespace quipper {

using PerfEvent = PerfDataProto_PerfEvent;
using SampleInfo = PerfDataProto_SampleInfo;
using StringAndMd5sumPrefix =
    PerfDataProto_StringMetadata_StringAndMd5sumPrefix;

namespace {

// The type of the storage size of a string, prefixed before each string field
// in raw data.
typedef u32 string_size_type;

// The type of the number of string data, found in the command line metadata in
// the perf data file.
typedef u32 num_string_data_type;

// Types of the event desc fields that are not found in other structs.
typedef u32 event_desc_num_events;
typedef u32 event_desc_attr_size;
typedef u32 event_desc_num_unique_ids;

// The type of the number of nodes field in NUMA topology.
typedef u32 numa_topology_num_nodes_type;

// A mask that is applied to |metadata_mask()| in order to get a mask for
// only the metadata supported by quipper.
const uint32_t kSupportedMetadataMask =
    1 << HEADER_TRACING_DATA |
    1 << HEADER_BUILD_ID |
    1 << HEADER_HOSTNAME |
    1 << HEADER_OSRELEASE |
    1 << HEADER_VERSION |
    1 << HEADER_ARCH |
    1 << HEADER_NRCPUS |
    1 << HEADER_CPUDESC |
    1 << HEADER_CPUID |
    1 << HEADER_TOTAL_MEM |
    1 << HEADER_CMDLINE |
    1 << HEADER_EVENT_DESC |
    1 << HEADER_CPU_TOPOLOGY |
    1 << HEADER_NUMA_TOPOLOGY |
    1 << HEADER_BRANCH_STACK;

// By default, the build ID event has PID = -1.
const uint32_t kDefaultBuildIDEventPid = static_cast<uint32_t>(-1);

// Eight bits in a byte.
size_t BytesToBits(size_t num_bytes) {
  return num_bytes * 8;
}

u8 ReverseByte(u8 x) {
  x = (x & 0xf0) >> 4 | (x & 0x0f) << 4;  // exchange nibbles
  x = (x & 0xcc) >> 2 | (x & 0x33) << 2;  // exchange pairs
  x = (x & 0xaa) >> 1 | (x & 0x55) << 1;  // exchange neighbors
  return x;
}

// If field points to the start of a bitfield padded to len bytes, this
// performs an endian swap of the bitfield, assuming the compiler that produced
// it conforms to the same ABI (bitfield layout is not completely specified by
// the language).
void SwapBitfieldOfBits(u8* field, size_t len) {
  for (size_t i = 0; i < len; i++) {
    field[i] = ReverseByte(field[i]);
  }
}

// The code currently assumes that the compiler will not add any padding to the
// various structs.  These CHECKs make sure that this is true.
void CheckNoEventHeaderPadding() {
  perf_event_header header;
  CHECK_EQ(sizeof(header),
           sizeof(header.type) + sizeof(header.misc) + sizeof(header.size));
}

void CheckNoPerfEventAttrPadding() {
  perf_event_attr attr;
  CHECK_EQ(sizeof(attr),
           (reinterpret_cast<u64>(&attr.__reserved_2) -
            reinterpret_cast<u64>(&attr)) +
           sizeof(attr.__reserved_2));
}

void CheckNoEventTypePadding() {
  perf_trace_event_type event_type;
  CHECK_EQ(sizeof(event_type),
           sizeof(event_type.event_id) + sizeof(event_type.name));
}

void CheckNoBuildIDEventPadding() {
  build_id_event event;
  CHECK_EQ(sizeof(event),
           sizeof(event.header.type) + sizeof(event.header.misc) +
           sizeof(event.header.size) + sizeof(event.pid) +
           sizeof(event.build_id));
}

// Creates a new build ID event with the given build ID string, filename, and
// misc value.
malloced_unique_ptr<build_id_event> CreateBuildIDEvent(const string& build_id,
                                                       const string& filename,
                                                       uint16_t misc) {
  size_t filename_len = GetUint64AlignedStringLength(filename);
  size_t size = sizeof(struct build_id_event) + filename_len;
  malloced_unique_ptr<build_id_event> event(CallocMemoryForBuildID(size));
  event->header.type = HEADER_BUILD_ID;
  event->header.misc = misc;
  event->header.size = size;

  event->pid = kDefaultBuildIDEventPid;
  snprintf(event->filename, filename_len, "%s", filename.c_str());
  memset(event->filename + filename.size(), 0, filename_len - filename.size());

  HexStringToRawData(build_id, event->build_id, sizeof(event->build_id));
  return event;
}

// Given a string, returns the total size required to store the string in perf
// data, including a preceding length field and extra padding to align the
// string + null terminator to a multiple of uint64s.
size_t ExpectedStorageSizeOf(const string& str) {
  return sizeof(string_size_type) + GetUint64AlignedStringLength(str);
}

// Reads a perf_event_header from |data| and performs byte swapping if
// necessary. Returns true on success, or false if there was an error.
bool ReadPerfEventHeader(DataReader* data, struct perf_event_header* header) {
  if (!data->ReadData(sizeof(struct perf_event_header), header)) {
    LOG(ERROR) << "Error reading perf event header.";
    return false;
  }
  if (data->is_cross_endian()) {
    ByteSwap(&header->type);
    ByteSwap(&header->size);
    ByteSwap(&header->misc);
  }
  return true;
}

// Reads a perf_file_section from |data| and performs byte swapping if
// necessary. Returns true on success, or false if there was an error.
bool ReadPerfFileSection(DataReader* data, struct perf_file_section* section) {
  if (!data->ReadData(sizeof(*section), section)) {
    LOG(ERROR) << "Error reading perf file section info.";
    return false;
  }
  if (data->is_cross_endian()) {
    ByteSwap(&section->offset);
    ByteSwap(&section->size);
  }
  return true;
}

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

}  // namespace

PerfReader::PerfReader() : is_cross_endian_(false) {
  // The metadata mask is stored in |proto_|. It should be initialized to 0
  // since it is used heavily.
  proto_.add_metadata_mask(0);
}

PerfReader::~PerfReader() {}

bool PerfReader::Serialize(PerfDataProto* perf_data_proto) const {
  perf_data_proto->CopyFrom(proto_);

  // Add a timestamp_sec to the protobuf.
  struct timeval timestamp_sec;
  if (!gettimeofday(&timestamp_sec, NULL))
    perf_data_proto->set_timestamp_sec(timestamp_sec.tv_sec);
  return true;
}

bool PerfReader::Deserialize(const PerfDataProto& perf_data_proto) {
  proto_.CopyFrom(perf_data_proto);

  // Iterate through all attrs and create a SampleInfoReader for each of them.
  // This is necessary for writing the proto representation of perf data to raw
  // data.
  for (const auto& stored_attr : proto_.file_attrs()) {
    PerfFileAttr attr;
    serializer_.DeserializePerfFileAttr(stored_attr, &attr);
    serializer_.CreateSampleInfoReader(attr, false /* read_cross_endian */);
  }
  return true;
}

bool PerfReader::ReadFile(const string& filename) {
  FileReader reader(filename);
  if (!reader.IsOpen()) {
    LOG(ERROR) << "Unable to open file " << filename;
    return false;
  }
  return ReadFromData(&reader);
}

bool PerfReader::ReadFromVector(const std::vector<char>& data) {
  return ReadFromPointer(data.data(), data.size());
}

bool PerfReader::ReadFromString(const string& str) {
  return ReadFromPointer(str.data(), str.size());
}

bool PerfReader::ReadFromPointer(const char* data, size_t size) {
  BufferReader buffer(data, size);
  return ReadFromData(&buffer);
}

bool PerfReader::ReadFromData(DataReader* data) {
  if (data->size() == 0) {
    LOG(ERROR) << "Input data is empty!";
    return false;
  }
  if (!ReadHeader(data))
    return false;

  // Check if it is normal perf data.
  if (header_.size == sizeof(header_)) {
    DVLOG(1) << "Perf data is in normal format.";

    // Make sure sections are within the size of the file. This check prevents
    // more obscure messages later when attempting to read from one of these
    // sections.
    if (header_.attrs.offset + header_.attrs.size > data->size()) {
      LOG(ERROR) << "Header says attrs section ends at "
                 << header_.attrs.offset + header_.attrs.size
                 << " bytes, which is larger than perf data size of "
                 << data->size() << " bytes.";
      return false;
    }
    if (header_.data.offset + header_.data.size > data->size()) {
      LOG(ERROR) << "Header says data section ends at "
                 << header_.data.offset + header_.data.size
                 << " bytes, which is larger than perf data size of "
                 << data->size() << " bytes.";
      return false;
    }
    if (header_.event_types.offset + header_.event_types.size > data->size()) {
      LOG(ERROR) << "Header says event_types section ends at "
                 << header_.event_types.offset + header_.event_types.size
                 << " bytes, which is larger than perf data size of "
                 << data->size() << " bytes.";
      return false;
    }

    if (!get_metadata_mask_bit(HEADER_EVENT_DESC)) {
      // Prefer to read attrs and event names from HEADER_EVENT_DESC metadata if
      // available. event_types section of perf.data is obsolete, but use it as
      // a fallback:
      if (!(ReadAttrsSection(data) && ReadEventTypesSection(data)))
        return false;
    }

    if (!(ReadMetadata(data) && ReadDataSection(data)))
      return false;

    // We can construct HEADER_EVENT_DESC from attrs and event types.
    // NB: Can't set this before ReadMetadata(), or it may misread the metadata.
    if (!event_types().empty())
      set_metadata_mask_bit(HEADER_EVENT_DESC);

    return true;
  }

  // Otherwise it is piped data.
  if (piped_header_.size != sizeof(piped_header_)) {
    LOG(ERROR) << "Expecting piped data format, but header size "
               << piped_header_.size << " does not match expected size "
               << sizeof(piped_header_);
    return false;
  }

  return ReadPipedData(data);
}

bool PerfReader::WriteFile(const string& filename) {
  std::vector<char> data;
  return WriteToVector(&data) && BufferToFile(filename, data);
}

bool PerfReader::WriteToVector(std::vector<char>* data) {
  data->resize(GetSize());
  return WriteToPointerWithoutCheckingSize(&data->at(0), data->size());
}

bool PerfReader::WriteToString(string* str) {
  str->resize(GetSize());
  return WriteToPointerWithoutCheckingSize(&str->at(0), str->size());
}

bool PerfReader::WriteToPointer(char* buffer, size_t size) {
  size_t required_size = GetSize();
  if (size < required_size) {
    LOG(ERROR) << "Buffer is too small - buffer size is " << size
               << " and required size is " << required_size;
    return false;
  }
  return WriteToPointerWithoutCheckingSize(buffer, size);
}

bool PerfReader::WriteToPointerWithoutCheckingSize(char* buffer, size_t size) {
  BufferWriter data(buffer, size);
  struct perf_file_header header;
  GenerateHeader(&header);

  return
      WriteHeader(header, &data) &&
      WriteAttrs(header, &data) &&
      WriteData(header, &data) &&
      WriteMetadata(header, &data);
}

size_t PerfReader::GetSize() const {
  struct perf_file_header header;
  GenerateHeader(&header);

  size_t total_size = 0;
  total_size += header.size;
  total_size += header.attrs.size;
  total_size += header.event_types.size;
  total_size += header.data.size;
  // Add the ID info, whose size is not explicitly included in the header.
  for (const auto& attr : proto_.file_attrs()) {
    total_size +=
        attr.ids_size() * sizeof(decltype(PerfFileAttr::ids)::value_type);
  }

  // Additional info about metadata.  See WriteMetadata for explanation.
  total_size += GetNumSupportedMetadata() * sizeof(struct perf_file_section);

  // Add the sizes of the various metadata.
  total_size += tracing_data().size();
  total_size += GetBuildIDMetadataSize();
  total_size += GetStringMetadataSize();
  total_size += GetUint32MetadataSize();
  total_size += GetUint64MetadataSize();
  total_size += GetEventDescMetadataSize();
  total_size += GetCPUTopologyMetadataSize();
  total_size += GetNUMATopologyMetadataSize();
  return total_size;
}

void PerfReader::GenerateHeader(struct perf_file_header* header) const {
  // This is the order of the input perf file contents in normal mode:
  // 1. Header
  // 2. Attribute IDs (pointed to by attr.ids.offset)
  // 3. Attributes
  // 4. Event types
  // 5. Data
  // 6. Metadata

  // Compute offsets in the above order.
  CheckNoEventHeaderPadding();
  memset(header, 0, sizeof(*header));
  header->magic = kPerfMagic;
  header->size = sizeof(*header);
  header->attr_size = sizeof(perf_file_attr);
  header->attrs.size = header->attr_size * attrs().size();
  for (const PerfEvent& event : proto_.events())
    header->data.size += event.header().size();
  // Do not use the event_types section. Use EVENT_DESC metadata instead.
  header->event_types.size = 0;

  u64 current_offset = 0;
  current_offset += header->size;
  for (const auto& attr : proto_.file_attrs()) {
    current_offset +=
        sizeof(decltype(PerfFileAttr::ids)::value_type) * attr.ids_size();
  }
  header->attrs.offset = current_offset;
  current_offset += header->attrs.size;
  header->event_types.offset = current_offset;
  current_offset += header->event_types.size;

  header->data.offset = current_offset;

  // Construct the header feature bits.
  memset(&header->adds_features, 0, sizeof(header->adds_features));
  // The following code makes the assumption that all feature bits are in the
  // first word of |adds_features|.  If the perf data format changes and the
  // assumption is no longer valid, this CHECK will fail, at which point the
  // below code needs to be updated.  For now, sticking to that assumption keeps
  // the code simple.
  // This assumption is also used when reading metadata, so that code
  // will also have to be updated if this CHECK starts to fail.
  CHECK_LE(static_cast<size_t>(HEADER_LAST_FEATURE),
           BytesToBits(sizeof(header->adds_features[0])));
  header->adds_features[0] |= metadata_mask() & kSupportedMetadataMask;
}

bool PerfReader::InjectBuildIDs(
    const std::map<string, string>& filenames_to_build_ids) {
  set_metadata_mask_bit(HEADER_BUILD_ID);
  std::set<string> updated_filenames;
  // Inject new build ID's for existing build ID events.
  for (auto& build_id : *proto_.mutable_build_ids()) {
    auto find_result = filenames_to_build_ids.find(build_id.filename());
    if (find_result == filenames_to_build_ids.end())
      continue;

    // TODO(sque): Should build IDs passed into this function be in binary
    // format? That would greatly simplify this section.
    const string& build_id_string = find_result->second;
    const int kHexCharsPerByte = 2;
    std::vector<uint8_t>
        build_id_data(build_id_string.size() / kHexCharsPerByte);
    if (!HexStringToRawData(build_id_string, build_id_data.data(),
                            build_id_data.size())) {
      LOG(ERROR) << "Could not convert hex string to raw data: "
                 << build_id_string;
      return false;
    }
    build_id.set_build_id_hash(build_id_data.data(), build_id_data.size());

    updated_filenames.insert(build_id.filename());
  }

  // For files with no existing build ID events, create new build ID events.
  // This requires a lookup of all MMAP's to determine the |misc| field of each
  // build ID event.
  std::map<string, uint16_t> filename_to_misc;
  for (const PerfEvent& event : proto_.events()) {
    if (event.header().type() == PERF_RECORD_MMAP ||
        event.header().type() == PERF_RECORD_MMAP2) {
      filename_to_misc[event.mmap_event().filename()] = event.header().misc();
    }
  }

  std::map<string, string>::const_iterator it;
  for (it = filenames_to_build_ids.begin();
       it != filenames_to_build_ids.end();
       ++it) {
    const string& filename = it->first;
    if (updated_filenames.find(filename) != updated_filenames.end())
      continue;

    // Determine the misc field.
    uint16_t new_misc = PERF_RECORD_MISC_KERNEL;
    std::map<string, uint16_t>::const_iterator misc_iter =
        filename_to_misc.find(filename);
    if (misc_iter != filename_to_misc.end())
      new_misc = misc_iter->second;

    string build_id = it->second;
    malloced_unique_ptr<build_id_event> event =
        CreateBuildIDEvent(build_id, filename, new_misc);
    if (!serializer_.SerializeBuildIDEvent(event, proto_.add_build_ids())) {
      LOG(ERROR) << "Could not serialize build ID event with ID " << build_id;
      return false;
    }
  }
  return true;
}

bool PerfReader::Localize(
    const std::map<string, string>& build_ids_to_filenames) {
  std::map<string, string> filename_map;
  for (auto& build_id : *proto_.mutable_build_ids()) {
    string build_id_string = RawDataToHexString(build_id.build_id_hash());
    auto find_result = build_ids_to_filenames.find(build_id_string);
    if (find_result == build_ids_to_filenames.end())
      continue;
    const string& new_filename = find_result->second;
    filename_map[build_id.filename()] = new_filename;
  }

  return LocalizeUsingFilenames(filename_map);
}

bool PerfReader::LocalizeUsingFilenames(
    const std::map<string, string>& filename_map) {
  LocalizeMMapFilenames(filename_map);
  for (auto& build_id : *proto_.mutable_build_ids()) {
    auto find_result = filename_map.find(build_id.filename());
    if (find_result != filename_map.end())
      build_id.set_filename(find_result->second);
  }
  return true;
}

void PerfReader::GetFilenames(std::vector<string>* filenames) const {
  std::set<string> filename_set;
  GetFilenamesAsSet(&filename_set);
  filenames->clear();
  filenames->insert(filenames->begin(), filename_set.begin(),
                    filename_set.end());
}

void PerfReader::GetFilenamesAsSet(std::set<string>* filenames) const {
  filenames->clear();
  for (const PerfEvent& event : proto_.events()) {
    if (event.header().type() == PERF_RECORD_MMAP ||
        event.header().type() == PERF_RECORD_MMAP2) {
      filenames->insert(event.mmap_event().filename());
    }
  }
}

void PerfReader::GetFilenamesToBuildIDs(
    std::map<string, string>* filenames_to_build_ids) const {
  filenames_to_build_ids->clear();
  for (const auto& build_id : proto_.build_ids()) {
    string build_id_string = RawDataToHexString(build_id.build_id_hash());
    PerfizeBuildIDString(&build_id_string);
    (*filenames_to_build_ids)[build_id.filename()] = build_id_string;
  }
}

void PerfReader::MaybeSortEventsByTime() {
  // Events can not be sorted by time if PERF_SAMPLE_TIME is not set in
  // attr.sample_type for all attrs.
  for (const auto& attr : attrs()) {
    if (!(attr.attr().sample_type() & PERF_SAMPLE_TIME)) {
      return;
    }
  }

  // Sort the events based on timestamp.
  std::stable_sort(proto_.mutable_events()->begin(),
                   proto_.mutable_events()->end(),
                   CompareEventTimes);
}

bool PerfReader::ReadHeader(DataReader* data) {
  CheckNoEventHeaderPadding();
  // The header is the first thing to be read. Don't use SeekSet(0) because it
  // doesn't make sense for piped files. Instead, verify that the reader points
  // to the start of the data.
  CHECK_EQ(0U, data->Tell());
  if (!data->ReadUint64(&piped_header_.magic)) {
    LOG(ERROR) << "Error reading header magic number.";
    return false;
  }

  if (piped_header_.magic != kPerfMagic &&
      piped_header_.magic != bswap_64(kPerfMagic)) {
    LOG(ERROR) << "Read wrong magic. Expected: 0x" << std::hex << kPerfMagic
               << " or 0x" << std::hex << bswap_64(kPerfMagic)
               << " Got: 0x" << std::hex << piped_header_.magic;
    return false;
  }
  is_cross_endian_ = (piped_header_.magic != kPerfMagic);
  data->set_is_cross_endian(is_cross_endian_);

  if (!data->ReadUint64(&piped_header_.size)) {
    LOG(ERROR) << "Error reading header size.";
    return false;
  }

  CHECK_EQ(data->Tell(), sizeof(piped_header_));

  // Header can be a piped header.
  if (piped_header_.size == sizeof(piped_header_))
    return true;

  // Read as a non-piped header.
  if (!data->ReadUint64(&header_.attr_size)) {
    LOG(ERROR) << "Error reading header::attr_size.";
    return false;
  }
  if (!ReadPerfFileSection(data, &header_.attrs) ||
      !ReadPerfFileSection(data, &header_.data) ||
      !ReadPerfFileSection(data, &header_.event_types)) {
    LOG(ERROR) << "Error reading header file section info.";
    return false;
  }

  const size_t features_size = sizeof(header_.adds_features);
  CHECK_EQ(data->Tell(), sizeof(header_) - features_size);

  if (!data->ReadData(features_size, header_.adds_features)) {
    LOG(ERROR) << "Error reading header::adds_features.";
    return false;
  }
  proto_.set_metadata_mask(0, header_.adds_features[0]);

  // Byte-swapping |adds_features| is tricky. It is defined as an array of
  // unsigned longs, which can vary between architectures. However, the overall
  // size of the array in bytes is fixed.
  //
  // According to perf's perf_file_header__read() function, the hostname feature
  // should always be set. Try byte-swapping as uint64s first and check the
  // hostname bit. If it's not set, then try swapping as uint32s. This is
  // similar to the algorithm used in perf.
  if (data->is_cross_endian()) {
    static_assert(sizeof(header_.adds_features[0]) == sizeof(uint32_t) ||
                  sizeof(header_.adds_features[0]) == sizeof(uint64_t),
                  "|header_.adds_features| must be defined as an array of "
                  "either 32-bit or 64-bit words.");

    uint64_t features64 = 0;
    // Some compilers will complain if we directly cast |header_.adds_features|
    // to a uint64_t*. Instead, determine the first uint64_t without using
    // pointer aliasing.
    if (sizeof(header_.adds_features[0]) == sizeof(uint64_t)) {
      features64 = bswap_64(header_.adds_features[0]);
    } else {
      // If the native |adds_features| is composed of 32-bit words, swap the
      // byte order of each word and then swap their positions to create a
      // 64-bit word.
      features64 =
          static_cast<uint64_t>(bswap_32(header_.adds_features[0])) << 32;
      features64 |= bswap_32(header_.adds_features[1]);
    }
    if (features64 & (1 << HEADER_HOSTNAME)) {
      for (size_t i = 0; i < features_size / sizeof(uint64_t); ++i)
        ByteSwap(reinterpret_cast<uint64_t*>(header_.adds_features) + i);
    } else {
      for (size_t i = 0; i < features_size / sizeof(uint32_t); ++i)
        ByteSwap(reinterpret_cast<uint32_t*>(header_.adds_features) + i);
    }
  }

  return true;
}

bool PerfReader::ReadAttrsSection(DataReader* data) {
  size_t num_attrs = header_.attrs.size / header_.attr_size;
  if (header_.attrs.size % header_.attr_size != 0) {
    LOG(ERROR) << "Total size of attrs " << header_.attrs.size
               << " is not a multiple of attr size " << header_.attr_size;
  }
  data->SeekSet(header_.attrs.offset);
  for (size_t i = 0; i < num_attrs; i++) {
    if (!ReadAttr(data))
      return false;
  }
  return true;
}

bool PerfReader::ReadAttr(DataReader* data) {
  PerfFileAttr attr;
  if (!ReadEventAttr(data, &attr.attr))
    return false;

  perf_file_section ids;
  if (!ReadPerfFileSection(data, &ids))
    return false;

  // The ID may be stored at a different location in the file than where we're
  // currently reading.
  size_t saved_offset = data->Tell();
  data->SeekSet(ids.offset);

  size_t num_ids = ids.size / sizeof(decltype(attr.ids)::value_type);
  if (!ReadUniqueIDs(data, num_ids, &attr.ids))
    return false;
  data->SeekSet(saved_offset);
  AddPerfFileAttr(attr);

  return true;
}

bool PerfReader::ReadEventAttr(DataReader* data, perf_event_attr* attr) {
  CheckNoPerfEventAttrPadding();
  *attr = {0};

  static_assert(
      offsetof(struct perf_event_attr, size) == sizeof(perf_event_attr::type),
      "type and size should be the first to fields of perf_event_attr");

  if (!data->ReadUint32(&attr->type) || !data->ReadUint32(&attr->size)) {
    LOG(ERROR) << "Error reading event attr type and size.";
    return false;
  }

  // Now read the rest of the attr struct.
  const size_t attr_offset = sizeof(attr->type) + sizeof(attr->size);
  const size_t attr_readable_size =
      std::min(static_cast<size_t>(attr->size), sizeof(*attr));
  if (!data->ReadDataValue(attr_readable_size - attr_offset, "attribute",
                           reinterpret_cast<char*>(attr) + attr_offset)) {
    return false;
  }
  data->SeekSet(data->Tell() + attr->size - attr_readable_size);

  if (data->is_cross_endian()) {
    // Depending on attr->size, some of these might not have actually been
    // read. This is okay: they are zero.
    ByteSwap(&attr->type);
    ByteSwap(&attr->size);
    ByteSwap(&attr->config);
    ByteSwap(&attr->sample_period);
    ByteSwap(&attr->sample_type);
    ByteSwap(&attr->read_format);

    // NB: This will also reverse precise_ip : 2 as if it was two fields:
    auto *const bitfield_start = &attr->read_format + 1;
    SwapBitfieldOfBits(reinterpret_cast<u8*>(bitfield_start), sizeof(u64));
    // ... So swap it back:
    const auto tmp = attr->precise_ip;
    attr->precise_ip = (tmp & 0x2) >> 1 | (tmp & 0x1) << 1;

    ByteSwap(&attr->wakeup_events);  // union with wakeup_watermark
    ByteSwap(&attr->bp_type);
    ByteSwap(&attr->bp_addr);        // union with config1
    ByteSwap(&attr->bp_len);         // union with config2
    ByteSwap(&attr->branch_sample_type);
    ByteSwap(&attr->sample_regs_user);
    ByteSwap(&attr->sample_stack_user);
  }

  // The actual perf_event_attr data size might be different from the size of
  // the struct definition.  Check against perf_event_attr's |size| field.
  attr->size = sizeof(*attr);

  return true;
}

bool PerfReader::ReadUniqueIDs(DataReader* data, size_t num_ids,
                               std::vector<u64>* ids) {
  ids->resize(num_ids);
  for (u64& id : *ids) {
    if (!data->ReadUint64(&id)) {
      LOG(ERROR) << "Error reading unique ID.";
      return false;
    }
  }
  return true;
}

bool PerfReader::ReadEventTypesSection(DataReader* data) {
  int num_event_types =
      header_.event_types.size / sizeof(struct perf_trace_event_type);
  if (num_event_types == 0) {
    // Not available.
    return true;
  }
  CHECK_EQ(proto_.file_attrs().size(), num_event_types);
  CHECK_EQ(sizeof(perf_trace_event_type) * num_event_types,
           header_.event_types.size);
  data->SeekSet(header_.event_types.offset);
  for (int i = 0; i < num_event_types; ++i) {
    if (!ReadEventType(data, i, 0))
      return false;
  }
  return true;
}

bool PerfReader::ReadEventType(DataReader* data, int attr_idx,
                               size_t event_size) {
  CheckNoEventTypePadding();
  decltype(perf_trace_event_type::event_id) event_id;

  if (!data->ReadUint64(&event_id)) {
    LOG(ERROR) << "Error reading event ID.";
    return false;
  }

  size_t event_name_len;
  if (event_size == 0) {  // Not in an event.
    event_name_len = sizeof(perf_trace_event_type::name);
  } else {
    event_name_len = event_size - sizeof(perf_event_header) - sizeof(event_id);
  }

  PerfFileAttr attr;
  if (!data->ReadString(event_name_len, &attr.name)) {
    LOG(ERROR) << "Not enough data left in data to read event name.";
    return false;
  }

  if (attr_idx >= proto_.file_attrs().size()) {
    LOG(ERROR) << "Too many event types, or attrs not read yet!";
    return false;
  }
  if (event_id != proto_.file_attrs(attr_idx).attr().config()) {
    LOG(ERROR) << "event_id for perf_trace_event_type (" << event_id << ") "
               << "does not match attr.config ("
               << proto_.file_attrs(attr_idx).attr().config() << ")";
    return false;
  }
  attr.attr.config = proto_.file_attrs(attr_idx).attr().config();

  serializer_.SerializePerfEventType(attr, proto_.add_event_types());
  return true;
}

bool PerfReader::ReadDataSection(DataReader* data) {
  u64 data_remaining_bytes = header_.data.size;
  data->SeekSet(header_.data.offset);
  while (data_remaining_bytes != 0) {
    // Read the header to determine the size of the event.
    perf_event_header header;
    if (!ReadPerfEventHeader(data, &header)) {
      LOG(ERROR) << "Error reading event header from data section.";
      return false;
    }

    // Read the rest of the event data.
    malloced_unique_ptr<event_t> event(CallocMemoryForEvent(header.size));
    event->header = header;
    if (!data->ReadDataValue(event->header.size - sizeof(event->header),
                             "rest of event", &event->header + 1)) {
      return false;
    }
    // TODO(sque): Find some way to combine this with the serialization below.
    MaybeSwapEventFields(event.get(), data->is_cross_endian());

    // We must have a valid way to read sample info before reading perf events.
    CHECK(serializer_.SampleInfoReaderAvailable());

    // Serialize the event to protobuf form.
    PerfEvent* proto_event = proto_.add_events();
    if (!serializer_.SerializeEvent(event, proto_event))
      return false;

    data_remaining_bytes -= event->header.size;
  }

  DLOG(INFO) << "Number of events stored: "<< proto_.events_size();
  return true;
}

bool PerfReader::ReadMetadata(DataReader* data) {
  // Metadata comes after the event data.
  data->SeekSet(header_.data.offset + header_.data.size);

  // Read the (offset, size) pairs of all the metadata elements. Note that this
  // takes into account all present metadata types, not just the ones included
  // in |kSupportedMetadataMask|. If a metadata type is not supported, it is
  // skipped over.
  std::vector<struct perf_file_section> sections(GetNumBits(metadata_mask()));
  for (struct perf_file_section& section : sections) {
    if (!ReadPerfFileSection(data, &section)) {
      LOG(ERROR) << "Error reading metadata entry info.";
      return false;
    }
  }

  auto section_iter = sections.begin();
  for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
    if (!get_metadata_mask_bit(type))
      continue;
    data->SeekSet(section_iter->offset);
    u64 size = section_iter->size;

    switch (type) {
    case HEADER_TRACING_DATA:
      if (!ReadTracingMetadata(data, size))
        return false;
      break;
    case HEADER_BUILD_ID:
      if (!ReadBuildIDMetadata(data, size))
        return false;
      break;
    case HEADER_HOSTNAME:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_hostname())) {
        return false;
      }
      break;
    case HEADER_OSRELEASE:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_kernel_version())) {
        return false;
      }
      break;
    case HEADER_VERSION:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_perf_version())) {
        return false;
      }
      break;
    case HEADER_ARCH:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_architecture())) {
        return false;
      }
      break;
    case HEADER_CPUDESC:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_cpu_description())) {
        return false;
      }
      break;
    case HEADER_CPUID:
      if (!ReadSingleStringMetadata(
              data, size,
              proto_.mutable_string_metadata()->mutable_cpu_id())) {
        return false;
      }
      break;
    case HEADER_CMDLINE:
    {
      auto* string_metadata = proto_.mutable_string_metadata();
      if (!ReadRepeatedStringMetadata(
              data, size,
              string_metadata->mutable_perf_command_line_token(),
              string_metadata->mutable_perf_command_line_whole())) {
        return false;
      }
      break;
    }
    case HEADER_NRCPUS:
      if (!ReadUint32Metadata(data, type, size))
        return false;
      break;
    case HEADER_TOTAL_MEM:
      if (!ReadUint64Metadata(data, type, size))
        return false;
      break;
    case HEADER_EVENT_DESC:
      if (!ReadEventDescMetadata(data, type, size))
        return false;
      break;
    case HEADER_CPU_TOPOLOGY:
      if (!ReadCPUTopologyMetadata(data, type, size))
        return false;
      break;
    case HEADER_NUMA_TOPOLOGY:
      if (!ReadNUMATopologyMetadata(data, type, size))
        return false;
      break;
    case HEADER_BRANCH_STACK:
      break;
    default:
      LOG(INFO) << "Unsupported metadata type, skipping: " << type;
      break;
    }
    ++section_iter;
  }

  return true;
}

bool PerfReader::ReadBuildIDMetadata(DataReader* data, size_t size) {
  CheckNoBuildIDEventPadding();
  while (size > 0) {
    // Make sure there is enough data for everything but the filename.
    perf_event_header build_id_header;
    if (!ReadPerfEventHeader(data, &build_id_header)) {
      LOG(ERROR) << "Error reading build ID header.";
      return false;
    }

    if (!ReadBuildIDMetadataWithoutHeader(data, build_id_header))
      return false;
    size -= build_id_header.size;
  }

  return true;
}

bool PerfReader::ReadBuildIDMetadataWithoutHeader(
    DataReader* data, const perf_event_header& header) {
  // Allocate memory for the event.
  malloced_unique_ptr<build_id_event>
      event(CallocMemoryForBuildID(header.size));
  event->header = header;

  // Make sure there is enough data for the rest of the event.
  if (!data->ReadDataValue(header.size - sizeof(header),
                           "rest of build ID event", &event->header + 1)) {
    LOG(ERROR) << "Not enough bytes to read build id event";
    return false;
  }
  if (data->is_cross_endian())
    ByteSwap(&event->pid);

  // Perf tends to use more space than necessary, so fix the size.
  event->header.size =
      sizeof(*event) + GetUint64AlignedStringLength(event->filename);

  if (!serializer_.SerializeBuildIDEvent(event, proto_.add_build_ids())) {
    LOG(ERROR) << "Could not serialize build ID event with ID "
               << RawDataToHexString(event->build_id, sizeof(event->build_id));
    return false;
  }
  return true;
}

bool PerfReader::ReadSingleStringMetadata(
    DataReader* data,
    size_t max_readable_size,
    StringAndMd5sumPrefix* dest) const {
  // If a string metadata field is present but empty, it can have a size of 0,
  // in which case there is nothing to be read.
  string single_string;
  if (max_readable_size && !data->ReadStringWithSizeFromData(&single_string))
    return false;
  dest->set_value(single_string);
  dest->set_value_md5_prefix(Md5Prefix(single_string));
  return true;
}

bool PerfReader::ReadRepeatedStringMetadata(
    DataReader* data,
    size_t max_readable_size,
    RepeatedPtrField<StringAndMd5sumPrefix>* dest_array,
    StringAndMd5sumPrefix* dest_single) const {
  num_string_data_type count = 1;
  if (!data->ReadUint32(&count)) {
    LOG(ERROR) << "Error reading string count.";
    return false;
  }
  size_t size_read = sizeof(count);

  string full_string;
  while (count-- > 0 && size_read < max_readable_size) {
    StringAndMd5sumPrefix* new_entry = dest_array->Add();
    size_t offset = data->Tell();
    if (!ReadSingleStringMetadata(data, max_readable_size - size_read,
                                  new_entry)) {
      return false;
    }

    if (!full_string.empty())
      full_string += " ";
    full_string += new_entry->value();

    size_read += data->Tell() - offset;
  }

  dest_single->set_value(full_string);
  dest_single->set_value_md5_prefix(Md5Prefix(full_string));
  return true;
}

bool PerfReader::ReadUint32Metadata(DataReader* data, u32 type, size_t size) {
  PerfUint32Metadata uint32_data;
  uint32_data.type = type;

  while (size > 0) {
    uint32_t item;
    if (!data->ReadUint32(&item)) {
      LOG(ERROR) << "Error reading uint32 metadata";
      return false;
    }

    uint32_data.data.push_back(item);
    size -= sizeof(item);
  }

  serializer_.SerializeSingleUint32Metadata(uint32_data,
                                            proto_.add_uint32_metadata());
  return true;
}

bool PerfReader::ReadUint64Metadata(DataReader* data, u32 type, size_t size) {
  PerfUint64Metadata uint64_data;
  uint64_data.type = type;

  while (size > 0) {
    uint64_t item;
    if (!data->ReadUint64(&item)) {
      LOG(ERROR) << "Error reading uint64 metadata";
      return false;
    }

    uint64_data.data.push_back(item);
    size -= sizeof(item);
  }

  serializer_.SerializeSingleUint64Metadata(uint64_data,
                                            proto_.add_uint64_metadata());
  return true;
}

// TODO(cwp-team): Move this to match the order in the header file.
bool PerfReader::ReadEventDescMetadata(DataReader* data, u32 type,
                                       size_t size) {
  // Structure:
  // u32 nr_events
  // u32 sizeof(perf_event_attr)
  // foreach event (nr_events):
  //   struct perf_event_attr
  //   u32 nr_ids
  //   event name (len & string, 64-bit padded)
  //   u64 ids[nr_ids]

  u32 nr_events;
  if (!data->ReadUint32(&nr_events)) {
    LOG(ERROR) << "Error reading event_desc nr_events.";
    return false;
  }

  u32 attr_size;
  if (!data->ReadUint32(&attr_size)) {
    LOG(ERROR) << "Error reading event_desc attr_size.";
    return false;
  }

  proto_.clear_file_attrs();
  proto_.mutable_file_attrs()->Reserve(nr_events);

  for (u32 i = 0; i < nr_events; i++) {
    PerfFileAttr attr;
    if (!ReadEventAttr(data, &attr.attr))
      return false;

    u32 nr_ids;
    if (!data->ReadUint32(&nr_ids)) {
      LOG(ERROR) << "Error reading event_desc nr_ids.";
      return false;
    }

    if (!data->ReadStringWithSizeFromData(&attr.name))
      return false;
    // TODO(sque): Read directly into proto_.file_attrs.
    std::vector<u64> &ids = attr.ids;
    ids.resize(nr_ids);
    for (u64& id : ids) {
      if (!data->ReadUint64(&id)) {
        LOG(ERROR) << "Error reading ID value for attr #" << i;
        return false;
      }
    }
    AddPerfFileAttr(attr);
    // The EVENT_DESC metadata is the newer replacement for the older event type
    // fields. In the protobuf, both types of data are stored in the
    // |event_types| field.
    serializer_.SerializePerfEventType(attr, proto_.add_event_types());
  }
  return true;
}

bool PerfReader::ReadCPUTopologyMetadata(DataReader* data, u32 type,
                                         size_t size) {
  num_siblings_type num_core_siblings;
  if (!data->ReadUint32(&num_core_siblings)) {
    LOG(ERROR) << "Error reading num core siblings.";
    return false;
  }

  PerfCPUTopologyMetadata cpu_topology;
  cpu_topology.core_siblings.resize(num_core_siblings);
  for (size_t i = 0; i < num_core_siblings; ++i) {
    if (!data->ReadStringWithSizeFromData(&cpu_topology.core_siblings[i]))
      return false;
  }

  num_siblings_type num_thread_siblings;
  if (!data->ReadUint32(&num_thread_siblings)) {
    LOG(ERROR) << "Error reading num core siblings.";
    return false;
  }

  cpu_topology.thread_siblings.resize(num_thread_siblings);
  for (size_t i = 0; i < num_thread_siblings; ++i) {
    if (!data->ReadStringWithSizeFromData(&cpu_topology.thread_siblings[i]))
      return false;
  }

  serializer_.SerializeCPUTopologyMetadata(cpu_topology,
                                           proto_.mutable_cpu_topology());
  return true;
}

bool PerfReader::ReadNUMATopologyMetadata(DataReader* data,
                                          u32 type,
                                          size_t size) {
  numa_topology_num_nodes_type num_nodes;
  if (!data->ReadUint32(&num_nodes)) {
    LOG(ERROR) << "Error reading NUMA topology num nodes.";
    return false;
  }

  for (size_t i = 0; i < num_nodes; ++i) {
    PerfNodeTopologyMetadata node;
    if (!data->ReadUint32(&node.id) ||
        !data->ReadUint64(&node.total_memory) ||
        !data->ReadUint64(&node.free_memory) ||
        !data->ReadStringWithSizeFromData(&node.cpu_list)) {
      LOG(ERROR) << "Error reading NUMA topology info for node #" << i;
      return false;
    }
    serializer_.SerializeNodeTopologyMetadata(node, proto_.add_numa_topology());
  }
  return true;
}

// TODO(cwp-team): Move this to match the order in the header file.
bool PerfReader::ReadTracingMetadata(DataReader* data, size_t size) {
  std::vector<char> tracing_data(size);
  if (!data->ReadDataValue(tracing_data.size(), "tracing_data",
                           tracing_data.data())) {
    return false;
  }
  serializer_.SerializeTracingMetadata(tracing_data, &proto_);
  return true;
}

bool PerfReader::ReadPipedData(DataReader* data) {
  // The piped data comes right after the file header.
  CHECK_EQ(piped_header_.size, data->Tell());
  bool result = true;
  int num_event_types = 0;

  CheckNoEventHeaderPadding();

  while (result && data->Tell() < data->size()) {
    perf_event_header header;
    if (!ReadPerfEventHeader(data, &header)) {
      LOG(ERROR) << "Error reading event header.";
      break;
    }

    if (header.size == 0) {
      // Avoid an infinite loop.
      LOG(ERROR) << "Event size is zero. Type: " << header.type;
      return false;
    }

    // Compute the size of the post-header part of the event data.
    size_t size_without_header = header.size - sizeof(header);

    if (header.type < PERF_RECORD_MAX) {
      // Allocate space for an event struct based on the size in the header.
      // Don't blindly allocate the entire event_t because it is a
      // variable-sized type that may include data beyond what's nominally
      // declared in its definition.
      malloced_unique_ptr<event_t> event(CallocMemoryForEvent(header.size));
      event->header = header;

      // Read the rest of the event data.
      if (!data->ReadDataValue(size_without_header, "rest of piped event",
                               &event->header + 1)) {
        break;
      }
      MaybeSwapEventFields(event.get(), data->is_cross_endian());

      // Serialize the event to protobuf form.
      PerfEvent* proto_event = proto_.add_events();
      if (!serializer_.SerializeEvent(event, proto_event))
        return false;

      continue;
    }

    switch (header.type) {
    case PERF_RECORD_HEADER_ATTR:
      result = ReadAttrEventBlock(data, size_without_header);
      break;
    case PERF_RECORD_HEADER_EVENT_TYPE:
      result = ReadEventType(data, num_event_types++, header.size);
      break;
    case PERF_RECORD_HEADER_EVENT_DESC:
      set_metadata_mask_bit(HEADER_EVENT_DESC);
      result = ReadEventDescMetadata(data, HEADER_EVENT_DESC,
                                     size_without_header);
      break;
    case PERF_RECORD_HEADER_TRACING_DATA:
      set_metadata_mask_bit(HEADER_TRACING_DATA);
      {
        // TRACING_DATA's header.size is a lie. It is the size of only the event
        // struct. The size of the data is in the event struct, and followed
        // immediately by the tracing header data.
        decltype(tracing_data_event::size) size = 0;
        if (!data->ReadUint32(&size)) {
          LOG(ERROR) << "Error reading tracing data size.";
          return false;
        }
        result = ReadTracingMetadata(data, size);
      }
      break;
    case PERF_RECORD_HEADER_BUILD_ID:
      set_metadata_mask_bit(HEADER_BUILD_ID);
      result = ReadBuildIDMetadataWithoutHeader(data, header);
      break;
    case PERF_RECORD_HEADER_HOSTNAME:
      set_metadata_mask_bit(HEADER_HOSTNAME);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_hostname());
      break;
    case PERF_RECORD_HEADER_OSRELEASE:
      set_metadata_mask_bit(HEADER_OSRELEASE);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_kernel_version());
      break;
    case PERF_RECORD_HEADER_VERSION:
      set_metadata_mask_bit(HEADER_VERSION);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_perf_version());
      break;
    case PERF_RECORD_HEADER_ARCH:
      set_metadata_mask_bit(HEADER_ARCH);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_architecture());
      break;
    case PERF_RECORD_HEADER_CPUDESC:
      set_metadata_mask_bit(HEADER_CPUDESC);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_cpu_description());
      break;
    case PERF_RECORD_HEADER_CPUID:
      set_metadata_mask_bit(HEADER_CPUID);
      result = ReadSingleStringMetadata(
                   data, size_without_header,
                   proto_.mutable_string_metadata()->mutable_cpu_id());
      break;
    case PERF_RECORD_HEADER_CMDLINE:
    {
      set_metadata_mask_bit(HEADER_CMDLINE);
      auto* string_metadata = proto_.mutable_string_metadata();
      result = ReadRepeatedStringMetadata(
                   data, size_without_header,
                   string_metadata->mutable_perf_command_line_token(),
                   string_metadata->mutable_perf_command_line_whole());
      break;
    }
    case PERF_RECORD_HEADER_NRCPUS:
      set_metadata_mask_bit(HEADER_NRCPUS);
      result = ReadUint32Metadata(data, HEADER_NRCPUS, size_without_header);
      break;
    case PERF_RECORD_HEADER_TOTAL_MEM:
      set_metadata_mask_bit(HEADER_TOTAL_MEM);
      result = ReadUint64Metadata(data, HEADER_TOTAL_MEM, size_without_header);
      break;
    case PERF_RECORD_HEADER_CPU_TOPOLOGY:
      set_metadata_mask_bit(HEADER_CPU_TOPOLOGY);
      result = ReadCPUTopologyMetadata(data, HEADER_CPU_TOPOLOGY,
                                       size_without_header);
      break;
    case PERF_RECORD_HEADER_NUMA_TOPOLOGY:
      set_metadata_mask_bit(HEADER_NUMA_TOPOLOGY);
      result = ReadNUMATopologyMetadata(data, HEADER_NUMA_TOPOLOGY,
                                        size_without_header);
      break;
    default:
      // For unsupported event types, log a warning only if the type is an
      // unknown type.
      if (header.type < PERF_RECORD_USER_TYPE_START ||
          header.type >= PERF_RECORD_HEADER_MAX) {
        LOG(WARNING) << "Unknown event type: " << header.type;
      }
      // Skip over the data in this event.
      data->SeekSet(data->Tell() + size_without_header);
      break;
    }
  }

  if (!result)
    return false;

  // The PERF_RECORD_HEADER_EVENT_TYPE events are obsolete, but if present
  // and PERF_RECORD_HEADER_EVENT_DESC metadata events are not, we should use
  // them. Otherwise, we should use prefer the _EVENT_DESC data.
  if (!get_metadata_mask_bit(HEADER_EVENT_DESC) &&
      num_event_types == proto_.file_attrs().size()) {
    // We can construct HEADER_EVENT_DESC:
    set_metadata_mask_bit(HEADER_EVENT_DESC);
  }

  return result;
}

bool PerfReader::WriteHeader(const struct perf_file_header& header,
                             DataWriter* data) const {
  CheckNoEventHeaderPadding();
  size_t size = sizeof(header);
  return data->WriteDataValue(&header, size, "file header");
}

bool PerfReader::WriteAttrs(const struct perf_file_header& header,
                            DataWriter* data) const {
  CheckNoPerfEventAttrPadding();
  const size_t id_offset = header.size;
  CHECK_EQ(id_offset, data->Tell());

  std::vector<struct perf_file_section> id_sections;
  id_sections.reserve(attrs().size());
  for (const auto& attr : proto_.file_attrs()) {
    size_t section_size =
        attr.ids_size() * sizeof(decltype(PerfFileAttr::ids)::value_type);
    id_sections.push_back(perf_file_section{data->Tell(), section_size});
    for (const uint64_t& id : attr.ids()) {
      if (!data->WriteDataValue(&id, sizeof(id), "ID info"))
        return false;
    }
  }

  CHECK_EQ(header.attrs.offset, data->Tell());
  for (int i = 0; i < attrs().size(); i++) {
    const struct perf_file_section& id_section = id_sections[i];
    PerfFileAttr attr;
    serializer_.DeserializePerfFileAttr(proto_.file_attrs(i), &attr);
    if (!data->WriteDataValue(&attr.attr, sizeof(attr.attr), "attribute") ||
        !data->WriteDataValue(&id_section, sizeof(id_section), "ID section")) {
      return false;
    }
  }
  return true;
}

bool PerfReader::WriteData(const struct perf_file_header& header,
                           DataWriter* data) const {
  // No need to CHECK anything if no event data is being written.
  if (proto_.events().empty())
    return true;

  CHECK(serializer_.SampleInfoReaderAvailable());
  CHECK_EQ(header.data.offset, data->Tell());
  for (const PerfEvent& proto_event : proto_.events()) {
    malloced_unique_ptr<event_t> event;
    // The nominal size given by |proto_event| may not be correct, as the
    // contents may have changed since the PerfEvent was created. Use the size
    // in the event_t returned by PerfSerializer::DeserializeEvent().
    if (!serializer_.DeserializeEvent(proto_event, &event) ||
        !data->WriteDataValue(event.get(), event->header.size, "event data")) {
      return false;
    }
  }
  return true;
}

bool PerfReader::WriteMetadata(const struct perf_file_header& header,
                               DataWriter* data) const {
  const size_t header_offset = header.data.offset + header.data.size;
  CHECK_EQ(header_offset, data->Tell());

  // There is one header for each feature pointing to the metadata for that
  // feature. If a feature has no metadata, the size field is zero.
  const size_t headers_size =
      GetNumSupportedMetadata() * sizeof(perf_file_section);
  const size_t metadata_offset = header_offset + headers_size;
  data->SeekSet(metadata_offset);

  // Record the new metadata offsets and sizes in this vector of info entries.
  std::vector<struct perf_file_section> metadata_sections;
  metadata_sections.reserve(GetNumSupportedMetadata());

  // For less verbose access to string metadata fields.
  const auto& string_metadata = proto_.string_metadata();

  for (u32 type = HEADER_FIRST_FEATURE; type != HEADER_LAST_FEATURE; ++type) {
    if ((header.adds_features[0] & (1 << type)) == 0)
      continue;

    struct perf_file_section header_entry;
    header_entry.offset = data->Tell();
    // Write actual metadata to address metadata_offset
    switch (type) {
    case HEADER_TRACING_DATA:
      if (!data->WriteDataValue(tracing_data().data(), tracing_data().size(),
                                "tracing data")) {
        return false;
      }
      break;
    case HEADER_BUILD_ID:
      if (!WriteBuildIDMetadata(type, data))
        return false;
      break;
    case HEADER_HOSTNAME:
      if (!WriteSingleStringMetadata(string_metadata.hostname(), data))
        return false;
      break;
    case HEADER_OSRELEASE:
      if (!WriteSingleStringMetadata(string_metadata.kernel_version(), data))
        return false;
      break;
    case HEADER_VERSION:
      if (!WriteSingleStringMetadata(string_metadata.perf_version(), data))
        return false;
      break;
    case HEADER_ARCH:
      if (!WriteSingleStringMetadata(string_metadata.architecture(), data))
        return false;
      break;
    case HEADER_CPUDESC:
      if (!WriteSingleStringMetadata(string_metadata.cpu_description(), data))
        return false;
      break;
    case HEADER_CPUID:
      if (!WriteSingleStringMetadata(string_metadata.cpu_id(), data))
        return false;
      break;
    case HEADER_CMDLINE:
      if (!WriteRepeatedStringMetadata(
              string_metadata.perf_command_line_token(),
              data)) {
        return false;
      }
      break;
    case HEADER_NRCPUS:
      if (!WriteUint32Metadata(type, data))
        return false;
      break;
    case HEADER_TOTAL_MEM:
      if (!WriteUint64Metadata(type, data))
        return false;
      break;
    case HEADER_EVENT_DESC:
      if (!WriteEventDescMetadata(type, data))
        return false;
      break;
    case HEADER_CPU_TOPOLOGY:
      if (!WriteCPUTopologyMetadata(type, data))
        return false;
      break;
    case HEADER_NUMA_TOPOLOGY:
      if (!WriteNUMATopologyMetadata(type, data))
        return false;
      break;
    case HEADER_BRANCH_STACK:
      break;
    default: LOG(ERROR) << "Unsupported metadata type: " << type;
      return false;
    }

    // Compute the size of the metadata that was just written. This is reflected
    // in how much the data write pointer has moved.
    header_entry.size = data->Tell() - header_entry.offset;
    metadata_sections.push_back(header_entry);
  }
  // Make sure we have recorded the right number of entries.
  CHECK_EQ(GetNumSupportedMetadata(), metadata_sections.size());

  // Now write the metadata offset and size info back to the metadata headers.
  size_t old_offset = data->Tell();
  data->SeekSet(header_offset);
  if (!data->WriteDataValue(metadata_sections.data(), headers_size,
                            "metadata section info")) {
    return false;
  }
  // Make sure the write pointer now points to the end of the metadata headers
  // and hence the beginning of the actual metadata.
  CHECK_EQ(metadata_offset, data->Tell());
  data->SeekSet(old_offset);

  return true;
}

bool PerfReader::WriteBuildIDMetadata(u32 type, DataWriter* data) const {
  CheckNoBuildIDEventPadding();
  for (const auto& build_id : proto_.build_ids()) {
    malloced_unique_ptr<build_id_event> event;
    if (!serializer_.DeserializeBuildIDEvent(build_id, &event)) {
      LOG(ERROR) << "Could not deserialize build ID event with build ID "
                 << RawDataToHexString(build_id.build_id_hash());
      return false;
    }
    if (!data->WriteDataValue(event.get(), event->header.size,
                              "Build ID metadata")) {
      return false;
    }
  }
  return true;
}

bool PerfReader::WriteSingleStringMetadata(const StringAndMd5sumPrefix& src,
                                           DataWriter* data) const {
  return data->WriteStringWithSizeToData(src.value());
}

bool PerfReader::WriteRepeatedStringMetadata(
    const RepeatedPtrField<StringAndMd5sumPrefix>& src_array,
    DataWriter* data) const {
  num_string_data_type num_strings = src_array.size();
  if (!data->WriteDataValue(&num_strings, sizeof(num_strings),
                           "number of string metadata")) {
    return false;
  }
  for (const auto& src_entry : src_array) {
    if (!data->WriteStringWithSizeToData(src_entry.value()))
      return false;
  }
  return true;
}

bool PerfReader::WriteUint32Metadata(u32 type, DataWriter* data) const {
  for (const auto& metadata : proto_.uint32_metadata()) {
    if (metadata.type() != type)
      continue;
    PerfUint32Metadata local_metadata;
    serializer_.DeserializeSingleUint32Metadata(metadata, &local_metadata);
    const std::vector<uint32_t>& raw_data = local_metadata.data;
    return data->WriteDataValue(raw_data.data(),
                                raw_data.size() * sizeof(uint32_t),
                                "uint32_t metadata");
  }
  LOG(ERROR) << "Uint32 metadata of type " << type << " not present";
  return false;
}

bool PerfReader::WriteUint64Metadata(u32 type, DataWriter* data) const {
  for (const auto& metadata : proto_.uint64_metadata()) {
    if (metadata.type() != type)
      continue;
    PerfUint64Metadata local_metadata;
    serializer_.DeserializeSingleUint64Metadata(metadata, &local_metadata);
    const std::vector<uint64_t>& raw_data = local_metadata.data;
    return data->WriteDataValue(raw_data.data(),
                                raw_data.size() * sizeof(uint64_t),
                                "uint32_t metadata");
  }
  LOG(ERROR) << "Uint64 metadata of type " << type << " not present";
  return false;
}

bool PerfReader::WriteEventDescMetadata(u32 type, DataWriter* data) const {
  CheckNoPerfEventAttrPadding();

  if (attrs().size() > event_types().size()) {
    LOG(ERROR) << "Number of attrs (" << attrs().size() << ") cannot exceed "
               << "number of event types (" << event_types().size() << ")";
    return false;
  }

  event_desc_num_events num_events = proto_.file_attrs().size();
  if (!data->WriteDataValue(&num_events, sizeof(num_events),
                            "event_desc num_events")) {
    return false;
  }
  event_desc_attr_size attr_size = sizeof(perf_event_attr);
  if (!data->WriteDataValue(&attr_size, sizeof(attr_size),
                            "event_desc attr_size")) {
    return false;
  }

  for (int i = 0; i < attrs().size(); ++i) {
    const auto& stored_attr = attrs().Get(i);
    PerfFileAttr attr;
    serializer_.DeserializePerfFileAttr(stored_attr, &attr);
    if (!serializer_.DeserializePerfEventType(proto_.event_types(i), &attr))
      return false;

    if (!data->WriteDataValue(&attr.attr, sizeof(attr.attr),
                              "event_desc attribute")) {
      return false;
    }

    event_desc_num_unique_ids num_ids = attr.ids.size();
    if (!data->WriteDataValue(&num_ids, sizeof(num_ids),
                              "event_desc num_unique_ids")) {
      return false;
    }

    if (!data->WriteStringWithSizeToData(attr.name))
      return false;

    if (!data->WriteDataValue(attr.ids.data(), num_ids * sizeof(attr.ids[0]),
                              "event_desc unique_ids")) {
      return false;
    }
  }
  return true;
}

bool PerfReader::WriteCPUTopologyMetadata(u32 type, DataWriter* data) const {
  PerfCPUTopologyMetadata cpu_topology;
  serializer_.DeserializeCPUTopologyMetadata(proto_.cpu_topology(),
                                             &cpu_topology);

  std::vector<string>& cores = cpu_topology.core_siblings;
  num_siblings_type num_cores = cores.size();
  if (!data->WriteDataValue(&num_cores, sizeof(num_cores), "num cores"))
    return false;
  for (string& core_name : cores) {
    if (!data->WriteStringWithSizeToData(core_name))
      return false;
  }

  std::vector<string>& threads = cpu_topology.thread_siblings;
  num_siblings_type num_threads = threads.size();
  if (!data->WriteDataValue(&num_threads, sizeof(num_threads), "num threads"))
    return false;
  for (string& thread_name : threads) {
    if (!data->WriteStringWithSizeToData(thread_name))
      return false;
  }

  return true;
}

bool PerfReader::WriteNUMATopologyMetadata(u32 type, DataWriter* data) const {
  numa_topology_num_nodes_type num_nodes = proto_.numa_topology().size();
  if (!data->WriteDataValue(&num_nodes, sizeof(num_nodes), "num nodes"))
    return false;

  for (const auto& node_proto : proto_.numa_topology()) {
    PerfNodeTopologyMetadata node;
    serializer_.DeserializeNodeTopologyMetadata(node_proto, &node);

    if (!data->WriteDataValue(&node.id, sizeof(node.id), "node id") ||
        !data->WriteDataValue(&node.total_memory, sizeof(node.total_memory),
                              "node total memory") ||
        !data->WriteDataValue(&node.free_memory, sizeof(node.free_memory),
                              "node free memory") ||
        !data->WriteStringWithSizeToData(node.cpu_list)) {
      return false;
    }
  }
  return true;
}

bool PerfReader::ReadAttrEventBlock(DataReader* data, size_t size) {
  const size_t initial_offset = data->Tell();
  PerfFileAttr attr;
  if (!ReadEventAttr(data, &attr.attr))
    return false;

  // attr.attr.size has been upgraded to the current size of perf_event_attr.
  const size_t actual_attr_size = data->Tell() - initial_offset;

  const size_t num_ids =
      (size - actual_attr_size) / sizeof(decltype(attr.ids)::value_type);
  if (!ReadUniqueIDs(data, num_ids, &attr.ids))
    return false;

  // Event types are found many times in the perf data file.
  // Only add this event type if it is not already present.
  for (const auto& stored_attr : proto_.file_attrs()) {
    if (stored_attr.ids(0) == attr.ids[0])
      return true;
  }
  AddPerfFileAttr(attr);
  return true;
}

void PerfReader::MaybeSwapEventFields(event_t* event, bool is_cross_endian) {
  if (!is_cross_endian)
    return;
  uint32_t type = event->header.type;
  switch (type) {
  case PERF_RECORD_SAMPLE:
    break;
  case PERF_RECORD_MMAP:
    ByteSwap(&event->mmap.pid);
    ByteSwap(&event->mmap.tid);
    ByteSwap(&event->mmap.start);
    ByteSwap(&event->mmap.len);
    ByteSwap(&event->mmap.pgoff);
    break;
  case PERF_RECORD_MMAP2:
    ByteSwap(&event->mmap2.pid);
    ByteSwap(&event->mmap2.tid);
    ByteSwap(&event->mmap2.start);
    ByteSwap(&event->mmap2.len);
    ByteSwap(&event->mmap2.pgoff);
    ByteSwap(&event->mmap2.maj);
    ByteSwap(&event->mmap2.min);
    ByteSwap(&event->mmap2.ino);
    ByteSwap(&event->mmap2.ino_generation);
    ByteSwap(&event->mmap2.prot);
    ByteSwap(&event->mmap2.flags);
    break;
  case PERF_RECORD_FORK:
  case PERF_RECORD_EXIT:
    ByteSwap(&event->fork.pid);
    ByteSwap(&event->fork.tid);
    ByteSwap(&event->fork.ppid);
    ByteSwap(&event->fork.ptid);
    ByteSwap(&event->fork.time);
    break;
  case PERF_RECORD_COMM:
    ByteSwap(&event->comm.pid);
    ByteSwap(&event->comm.tid);
    break;
  case PERF_RECORD_LOST:
    ByteSwap(&event->lost.id);
    ByteSwap(&event->lost.lost);
    break;
  case PERF_RECORD_THROTTLE:
  case PERF_RECORD_UNTHROTTLE:
    ByteSwap(&event->throttle.time);
    ByteSwap(&event->throttle.id);
    ByteSwap(&event->throttle.stream_id);
    break;
  case PERF_RECORD_READ:
    ByteSwap(&event->read.pid);
    ByteSwap(&event->read.tid);
    ByteSwap(&event->read.value);
    ByteSwap(&event->read.time_enabled);
    ByteSwap(&event->read.time_running);
    ByteSwap(&event->read.id);
    break;
  default:
    LOG(FATAL) << "Unknown event type: " << type;
  }

  // Do not swap the sample info fields that are not explicitly listed in the
  // struct definition of each event type. Leave that up to SampleInfoReader
  // within |serializer_|.
}

size_t PerfReader::GetNumSupportedMetadata() const {
  return GetNumBits(metadata_mask() & kSupportedMetadataMask);
}

size_t PerfReader::GetEventDescMetadataSize() const {
  if (attrs().size() > event_types().size()) {
    LOG(ERROR) << "Number of attrs (" << attrs().size() << ") cannot exceed "
               << "number of event types (" << event_types().size() << ")";
    return 0;
  }

  size_t size = 0;
  if (get_metadata_mask_bit(HEADER_EVENT_DESC)) {
    size += sizeof(event_desc_num_events) + sizeof(event_desc_attr_size);
    for (int i = 0; i < attrs().size(); ++i) {
      size += sizeof(perf_event_attr);
      size += sizeof(event_desc_num_unique_ids);
      size += ExpectedStorageSizeOf(event_types().Get(i).name());
      size += attrs().Get(i).ids_size() *
              sizeof(decltype(PerfFileAttr::ids)::value_type);
    }
  }
  return size;
}

size_t PerfReader::GetBuildIDMetadataSize() const {
  size_t size = 0;
  for (const auto& build_id : proto_.build_ids()) {
    size += sizeof(build_id_event) +
            GetUint64AlignedStringLength(build_id.filename());
  }
  return size;
}

size_t PerfReader::GetStringMetadataSize() const {
  size_t size = 0;
  if (string_metadata().has_hostname())
    size += ExpectedStorageSizeOf(string_metadata().hostname().value());
  if (string_metadata().has_kernel_version())
    size += ExpectedStorageSizeOf(string_metadata().kernel_version().value());
  if (string_metadata().has_perf_version())
    size += ExpectedStorageSizeOf(string_metadata().perf_version().value());
  if (string_metadata().has_architecture())
    size += ExpectedStorageSizeOf(string_metadata().architecture().value());
  if (string_metadata().has_cpu_description())
    size += ExpectedStorageSizeOf(string_metadata().cpu_description().value());
  if (string_metadata().has_cpu_id())
    size += ExpectedStorageSizeOf(string_metadata().cpu_id().value());

  if (!string_metadata().perf_command_line_token().empty()) {
    size += sizeof(num_string_data_type);
    for (const auto& token : string_metadata().perf_command_line_token())
      size += ExpectedStorageSizeOf(token.value());
  }
  return size;
}

size_t PerfReader::GetUint32MetadataSize() const {
  size_t size = 0;
  for (const auto& metadata : proto_.uint32_metadata())
    size += metadata.data().size() * sizeof(uint32_t);
  return size;
}

size_t PerfReader::GetUint64MetadataSize() const {
  size_t size = 0;
  for (const auto& metadata : proto_.uint64_metadata())
    size += metadata.data().size() * sizeof(uint64_t);
  return size;
}

size_t PerfReader::GetCPUTopologyMetadataSize() const {
  // Core siblings.
  size_t size = sizeof(num_siblings_type);
  for (const string& core_sibling : proto_.cpu_topology().core_siblings())
    size += ExpectedStorageSizeOf(core_sibling);

  // Thread siblings.
  size += sizeof(num_siblings_type);
  for (const string& thread_sibling : proto_.cpu_topology().thread_siblings())
    size += ExpectedStorageSizeOf(thread_sibling);

  return size;
}

size_t PerfReader::GetNUMATopologyMetadataSize() const {
  size_t size = sizeof(numa_topology_num_nodes_type);
  for (const auto& node : proto_.numa_topology()) {
    size += sizeof(node.id());
    size += sizeof(node.total_memory()) + sizeof(node.free_memory());
    size += ExpectedStorageSizeOf(node.cpu_list());
  }
  return size;
}

bool PerfReader::NeedsNumberOfStringData(u32 type) const {
  return type == HEADER_CMDLINE;
}

bool PerfReader::LocalizeMMapFilenames(
    const std::map<string, string>& filename_map) {
  CHECK(serializer_.SampleInfoReaderAvailable());

  // Search for mmap/mmap2 events for which the filename needs to be updated.
  for (PerfEvent& event : *proto_.mutable_events()) {
    if (event.header().type() != PERF_RECORD_MMAP &&
        event.header().type() != PERF_RECORD_MMAP2) {
      continue;
    }
    const string& filename = event.mmap_event().filename();
    const auto it = filename_map.find(filename);
    if (it == filename_map.end())  // not found
      continue;

    const string& new_filename = it->second;
    size_t old_len = GetUint64AlignedStringLength(filename);
    size_t new_len = GetUint64AlignedStringLength(new_filename);
    size_t new_size = event.header().size() - old_len + new_len;

    event.mutable_mmap_event()->set_filename(new_filename);
    event.mutable_header()->set_size(new_size);
  }

  return true;
}

void PerfReader::AddPerfFileAttr(const PerfFileAttr& attr) {
  serializer_.SerializePerfFileAttr(attr, proto_.add_file_attrs());

  // Generate a new SampleInfoReader with the new attr.
  serializer_.CreateSampleInfoReader(attr, is_cross_endian_);
}

}  // namespace quipper
