// 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/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/perf_data_structures.h"
#include "chromiumos-wide-profiling/perf_data_utils.h"
#include "chromiumos-wide-profiling/sample_info_reader.h"
#include "chromiumos-wide-profiling/utils.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;
}

}  // 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_)) {
    DLOG(INFO) << "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) && WriteDataToFile(data, filename);
}

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;
  }
}

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:
      LOG(WARNING) << "Event type " << header.type << " is not yet supported!";
      // 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 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
