// 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_serializer.h"

#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>

#include <bitset>
#include <utility>

#include "base/logging.h"

#include "chromiumos-wide-profiling/compat/string.h"
#include "chromiumos-wide-profiling/sample_info_reader.h"
#include "chromiumos-wide-profiling/utils.h"

namespace quipper {

PerfSerializer::PerfSerializer() : serialize_sorted_events_(true) {
}

PerfSerializer::~PerfSerializer() {
}

bool PerfSerializer::SerializeFromFile(const string& filename,
                                       PerfDataProto* perf_data_proto) {
  if (!ReadFile(filename))
    return false;
  return Serialize(perf_data_proto);
}

bool PerfSerializer::Serialize(PerfDataProto* perf_data_proto) {
  if (!SerializePerfFileAttrs(attrs_, perf_data_proto->mutable_file_attrs())) {
    return false;
  }

  if (HaveEventNames() &&
      !SerializePerfEventTypes(
          attrs_, perf_data_proto->mutable_event_types())) {
    return false;
  }

  if (!parser_.ParseRawEvents()) {
    return false;
  }

  // Serialize events in either chronological (if possible) or raw data order.
  if (!serialize_sorted_events_ &&
      !SerializeEvents(parser_.parsed_events(),
                       perf_data_proto->mutable_events())) {
    return false;
  } else if (serialize_sorted_events_ &&
      !SerializeEventPointers(
          parser_.GetEventsSortedByTime(),
          perf_data_proto->mutable_events())) {
    return false;
  }

  perf_data_proto->add_metadata_mask(metadata_mask_);

  if (!SerializeMetadata(perf_data_proto)) {
    return false;
  }

  // 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);

  const PerfEventStats& stats = parser_.stats();
  PerfDataProto_PerfEventStats* stats_pb = perf_data_proto->mutable_stats();
  stats_pb->set_num_sample_events(stats.num_sample_events);
  stats_pb->set_num_mmap_events(stats.num_mmap_events);
  stats_pb->set_num_fork_events(stats.num_fork_events);
  stats_pb->set_num_exit_events(stats.num_exit_events);
  stats_pb->set_did_remap(stats.did_remap);
  stats_pb->set_num_sample_events_mapped(stats.num_sample_events_mapped);
  return true;
}

bool PerfSerializer::DeserializeToFile(const PerfDataProto& perf_data_proto,
                                       const string& filename) {
  return Deserialize(perf_data_proto) && WriteFile(filename);
}

bool PerfSerializer::Deserialize(const PerfDataProto& perf_data_proto) {
  if (!DeserializePerfFileAttrs(perf_data_proto.file_attrs(), &attrs_))
    return false;
  if (static_cast<size_t>(perf_data_proto.event_types().size()) ==
      attrs_.size() &&
      !DeserializePerfEventTypes(perf_data_proto.event_types(), &attrs_)) {
    return false;
  }

  // Make sure all event types (attrs) have the same sample type.
  for (size_t i = 0; i < attrs_.size(); ++i) {
    CHECK_EQ(attrs_[i].attr.sample_type, attrs_[0].attr.sample_type)
        << "Sample type for attribute #" << i
        << " (" << std::hex << attrs_[i].attr.sample_type << ")"
        << " does not match that of attribute 0"
        << " (" << std::hex << attrs_[0].attr.sample_type << ")";
  }
  CHECK_GT(attrs_.size(), 0U);
  sample_type_ = attrs_[0].attr.sample_type;
  read_format_ = attrs_[0].attr.read_format;
  sample_info_reader_.reset(
      new SampleInfoReader(attrs_[0].attr, false /* read_cross_endian */));

  if (!DeserializeEvents(perf_data_proto.events(), &events_)) {
    return false;
  }

  if (!parser_.ParseRawEvents())
    return false;

  if (perf_data_proto.metadata_mask_size())
    metadata_mask_ = perf_data_proto.metadata_mask(0);

  if (!DeserializeMetadata(perf_data_proto)) {
    return false;
  }

  const PerfDataProto_PerfEventStats& stats_pb = perf_data_proto.stats();
  PerfEventStats stats = {0};
  stats.num_sample_events = stats_pb.num_sample_events();
  stats.num_mmap_events = stats_pb.num_mmap_events();
  stats.num_fork_events = stats_pb.num_fork_events();
  stats.num_exit_events = stats_pb.num_exit_events();
  stats.did_remap = stats_pb.did_remap();
  stats.num_sample_events_mapped = stats_pb.num_sample_events_mapped();
  parser_.mutable_stats() = stats;

  return true;
}

bool PerfSerializer::SerializePerfFileAttr(
    const PerfFileAttr& perf_file_attr,
    PerfDataProto_PerfFileAttr* perf_file_attr_proto) const {
  if (!SerializePerfEventAttr(perf_file_attr.attr,
                              perf_file_attr_proto->mutable_attr())) {
    return false;
  }

  for (size_t i = 0; i < perf_file_attr.ids.size(); i++ )
    perf_file_attr_proto->add_ids(perf_file_attr.ids[i]);
  return true;
}

bool PerfSerializer::DeserializePerfFileAttr(
    const PerfDataProto_PerfFileAttr& perf_file_attr_proto,
    PerfFileAttr* perf_file_attr) const {
  if (!DeserializePerfEventAttr(perf_file_attr_proto.attr(),
                                &perf_file_attr->attr)) {
    return false;
  }

  for (int i = 0; i < perf_file_attr_proto.ids_size(); i++ )
    perf_file_attr->ids.push_back(perf_file_attr_proto.ids(i));
  return true;
}

bool PerfSerializer::SerializePerfEventAttr(
    const perf_event_attr& perf_event_attr,
    PerfDataProto_PerfEventAttr* perf_event_attr_proto) const {
#define S(x) perf_event_attr_proto->set_##x(perf_event_attr.x)
  S(type);
  S(size);
  S(config);
  if (perf_event_attr_proto->freq())
    S(sample_freq);
  else
    S(sample_period);
  S(sample_type);
  S(read_format);
  S(disabled);
  S(inherit);
  S(pinned);
  S(exclusive);
  S(exclude_user);
  S(exclude_kernel);
  S(exclude_hv);
  S(exclude_idle);
  S(mmap);
  S(comm);
  S(freq);
  S(inherit_stat);
  S(enable_on_exec);
  S(task);
  S(watermark);
  S(precise_ip);
  S(mmap_data);
  S(sample_id_all);
  S(exclude_host);
  S(exclude_guest);
  S(exclude_callchain_kernel);
  S(exclude_callchain_user);
  S(mmap2);
  S(comm_exec);
  if (perf_event_attr_proto->watermark())
    S(wakeup_watermark);
  else
    S(wakeup_events);
  S(bp_type);
  S(bp_addr);  // TODO(dhsharp): or config1?
  S(bp_len);   // TODO(dhsharp): or config2?
  S(branch_sample_type);
  S(sample_regs_user);
  S(sample_stack_user);
#undef S
  return true;
}

bool PerfSerializer::DeserializePerfEventAttr(
    const PerfDataProto_PerfEventAttr& perf_event_attr_proto,
    perf_event_attr* perf_event_attr) const {
  memset(perf_event_attr, 0, sizeof(*perf_event_attr));
#define S(x) perf_event_attr->x = perf_event_attr_proto.x()
  S(type);
  S(size);
  S(config);
  if (perf_event_attr->freq)
    S(sample_freq);
  else
    S(sample_period);
  S(sample_type);
  S(read_format);
  S(disabled);
  S(inherit);
  S(pinned);
  S(exclusive);
  S(exclude_user);
  S(exclude_kernel);
  S(exclude_hv);
  S(exclude_idle);
  S(mmap);
  S(comm);
  S(freq);
  S(inherit_stat);
  S(enable_on_exec);
  S(task);
  S(watermark);
  S(precise_ip);
  S(mmap_data);
  S(sample_id_all);
  S(exclude_host);
  S(exclude_guest);
  S(exclude_callchain_kernel);
  S(exclude_callchain_user);
  S(mmap2);
  S(comm_exec);
  if (perf_event_attr->watermark)
    S(wakeup_watermark);
  else
    S(wakeup_events);
  S(bp_type);
  S(bp_addr);  // TODO(dhsharp): or config1?
  S(bp_len);   // TODO(dhsharp): or config2?
  S(branch_sample_type);
  S(sample_regs_user);
  S(sample_stack_user);
#undef S
  return true;
}

bool PerfSerializer::SerializePerfEventType(
    const PerfFileAttr& event_attr,
    quipper::PerfDataProto_PerfEventType* event_type_proto) const {
  event_type_proto->set_id(event_attr.attr.config);
  event_type_proto->set_name(event_attr.name);
  event_type_proto->set_name_md5_prefix(Md5Prefix(event_attr.name));
  return true;
}

bool PerfSerializer::DeserializePerfEventType(
    const quipper::PerfDataProto_PerfEventType& event_type_proto,
    PerfFileAttr* event_attr) const {
  // Attr should have already been deserialized.
  if (event_attr->attr.config != event_type_proto.id()) {
    LOG(ERROR) << "Deserializing event types, id did not match attr.config. "
                  "Not deserializing the event name!";
    return false;
  }
  event_attr->name = event_type_proto.name();
  return true;
}

bool PerfSerializer::SerializeEventPointer(
    const ParsedEvent* event_ptr,
    PerfDataProto_PerfEvent* event_proto) const {
  const ParsedEvent& event = *event_ptr;
  return SerializeEvent(event, event_proto);
}

bool PerfSerializer::SerializeEvent(
    const ParsedEvent& event,
    PerfDataProto_PerfEvent* event_proto) const {
  const event_t& raw_event = *event.raw_event;
  if (!SerializeEventHeader(raw_event.header, event_proto->mutable_header()))
    return false;
  switch (raw_event.header.type) {
    case PERF_RECORD_SAMPLE:
      if (!SerializeRecordSample(raw_event,
                                 event_proto->mutable_sample_event())) {
        return false;
      }
      break;
    case PERF_RECORD_MMAP:
      if (!SerializeMMapSample(raw_event, event_proto->mutable_mmap_event()))
        return false;
      break;
    case PERF_RECORD_MMAP2:
      if (!SerializeMMap2Sample(raw_event, event_proto->mutable_mmap_event()))
        return false;
      break;
    case PERF_RECORD_COMM:
      if (!SerializeCommSample(raw_event, event_proto->mutable_comm_event()))
        return false;
      break;
    case PERF_RECORD_EXIT:
      if (!SerializeForkExitSample(raw_event,
                                   event_proto->mutable_exit_event())) {
        return false;
      }
      break;
    case PERF_RECORD_FORK:
      if (!SerializeForkExitSample(raw_event,
                                   event_proto->mutable_fork_event())) {
        return false;
      }
      break;
    case PERF_RECORD_LOST:
      if (!SerializeLostSample(raw_event, event_proto->mutable_lost_event()))
        return false;
      break;
    case PERF_RECORD_THROTTLE:
    case PERF_RECORD_UNTHROTTLE:
      if (!SerializeThrottleSample(raw_event,
                                   event_proto->mutable_throttle_event())) {
        return false;
      }
      break;
    case PERF_RECORD_READ:
      if (!SerializeReadSample(raw_event, event_proto->mutable_read_event()))
        return false;
      break;
    default:
      LOG(ERROR) << "Unknown raw_event type: " << raw_event.header.type;
      break;
  }
  return true;
}

bool PerfSerializer::DeserializeEvent(
    const PerfDataProto_PerfEvent& event_proto,
    malloced_unique_ptr<event_t>* event) const {
  // The deserialized header.size should not be completely trusted, because the
  // event content may have been changed (eg, md5 string replacement).
  // Since we don't know how much memory to allocate, use an oversized event_t
  // until the final size is known.
  // TODO(dhsharp): Come up with a better size prediction. We don't want to
  // overrun the allocated space. sizeof(event_t) is almost meaningless wrt the
  // space necessary for the event--it is the size of the largest member of the
  // union. For better or worse, this is dominated by the PATH_MAX-sized array
  // in struct mmap2_event. However, events also have a "sample id" placed
  // immediately after the struct. Previously to this, an on-stack event_t was
  // used, which is dangerous because the stack could have been overrun. Since
  // no issues were reported, we can presume that amount of space was
  // sufficient.
  perf_event_header header = {};
  if (!DeserializeEventHeader(event_proto.header(), &header))
    return false;
  const size_t alloc_event_size = header.size + 4096;
  malloced_unique_ptr<event_t> temp_event(
      CallocMemoryForEvent(alloc_event_size));
  temp_event->header = header;
  bool event_deserialized = false;
  switch (event_proto.header().type()) {
    case PERF_RECORD_SAMPLE:
      if (DeserializeRecordSample(event_proto.sample_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_MMAP:
      if (DeserializeMMapSample(event_proto.mmap_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_MMAP2:
      if (DeserializeMMap2Sample(event_proto.mmap_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_COMM:
      if (DeserializeCommSample(event_proto.comm_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_EXIT:
      if (event_proto.has_exit_event() &&
          DeserializeForkExitSample(event_proto.exit_event(),
                                    temp_event.get())) {
        event_deserialized = true;
      } else if (event_proto.has_fork_event() &&
                 DeserializeForkExitSample(event_proto.fork_event(),
                                           temp_event.get())) {
        // Some older protobufs use the |fork_event| field to store exit events.
        event_deserialized = true;
      }
      break;
    case PERF_RECORD_FORK:
      if (DeserializeForkExitSample(event_proto.fork_event(),
                                    temp_event.get())) {
        event_deserialized = true;
      }
      break;
    case PERF_RECORD_LOST:
      if (DeserializeLostSample(event_proto.lost_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_THROTTLE:
    case PERF_RECORD_UNTHROTTLE:
      if (DeserializeThrottleSample(event_proto.throttle_event(),
                                    temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_READ:
      if (DeserializeReadSample(event_proto.read_event(), temp_event.get()))
        event_deserialized = true;
      break;
    case PERF_RECORD_MAX:
    default:
      break;
  }
  if (!event_deserialized) {
    LOG(ERROR) << "Could not deserialize event of type "
               << event_proto.header().type();
    event->reset();
    return false;
  }
  // Reallocate the event down to its final size.
  const size_t final_event_size = temp_event->header.size;
  CHECK_LE(final_event_size, alloc_event_size)
      << "Likely overran the event buffer.";
  temp_event.reset(ReallocMemoryForEvent(temp_event.release(),
                                         final_event_size));

  *event = std::move(temp_event);
  return true;
}

bool PerfSerializer::SerializeEventHeader(
    const perf_event_header& header,
    PerfDataProto_EventHeader* header_proto) const {
  header_proto->set_type(header.type);
  header_proto->set_misc(header.misc);
  header_proto->set_size(header.size);
  return true;
}

bool PerfSerializer::DeserializeEventHeader(
    const PerfDataProto_EventHeader& header_proto,
    perf_event_header* header) const {
  header->type = header_proto.type();
  header->misc = header_proto.misc();
  header->size = header_proto.size();
  return true;
}

bool PerfSerializer::SerializeRecordSample(
    const event_t& event,
    PerfDataProto_SampleEvent* sample) const {
  perf_sample sample_info;
  if (!ReadPerfSampleInfo(event, &sample_info))
    return false;

  if (sample_type_ & PERF_SAMPLE_IP)
    sample->set_ip(sample_info.ip);
  if (sample_type_ & PERF_SAMPLE_TID) {
    sample->set_pid(sample_info.pid);
    sample->set_tid(sample_info.tid);
  }
  if (sample_type_ & PERF_SAMPLE_TIME)
    sample->set_sample_time_ns(sample_info.time);
  if (sample_type_ & PERF_SAMPLE_ADDR)
    sample->set_addr(sample_info.addr);
  if (sample_type_ & PERF_SAMPLE_ID)
    sample->set_id(sample_info.id);
  if (sample_type_ & PERF_SAMPLE_STREAM_ID)
    sample->set_stream_id(sample_info.stream_id);
  if (sample_type_ & PERF_SAMPLE_CPU)
    sample->set_cpu(sample_info.cpu);
  if (sample_type_ & PERF_SAMPLE_PERIOD)
    sample->set_period(sample_info.period);
  // TODO(sque): We don't have a use case for the raw data so just store the
  // size.  The data is assumed to be all zeroes.  So far it has been such.
  if (sample_type_ & PERF_SAMPLE_RAW)
    sample->set_raw_size(sample_info.raw_size);
  if (sample_type_ & PERF_SAMPLE_CALLCHAIN) {
    for (size_t i = 0; i < sample_info.callchain->nr; ++i)
      sample->add_callchain(sample_info.callchain->ips[i]);
  }
  if (sample_type_ & PERF_SAMPLE_BRANCH_STACK) {
    for (size_t i = 0; i < sample_info.branch_stack->nr; ++i) {
      sample->add_branch_stack();
      const struct branch_entry& entry = sample_info.branch_stack->entries[i];
      sample->mutable_branch_stack(i)->set_from_ip(entry.from);
      sample->mutable_branch_stack(i)->set_to_ip(entry.to);
      sample->mutable_branch_stack(i)->set_mispredicted(entry.flags.mispred);
    }
  }

  if (sample_type_ & PERF_SAMPLE_WEIGHT)
    sample->set_weight(sample_info.weight);
  if (sample_type_ & PERF_SAMPLE_DATA_SRC)
    sample->set_data_src(sample_info.data_src);
  if (sample_type_ & PERF_SAMPLE_TRANSACTION)
    sample->set_transaction(sample_info.transaction);

  return true;
}

bool PerfSerializer::DeserializeRecordSample(
    const PerfDataProto_SampleEvent& sample,
    event_t* event) const {
  perf_sample sample_info;
  if (sample.has_ip())
    sample_info.ip = sample.ip();
  if (sample.has_pid()) {
    CHECK(sample.has_tid()) << "Cannot have PID without TID.";
    sample_info.pid = sample.pid();
    sample_info.tid = sample.tid();
  }
  if (sample.has_sample_time_ns())
    sample_info.time = sample.sample_time_ns();
  if (sample.has_addr())
    sample_info.addr = sample.addr();
  if (sample.has_id())
    sample_info.id = sample.id();
  if (sample.has_stream_id())
    sample_info.stream_id = sample.stream_id();
  if (sample.has_cpu())
    sample_info.cpu = sample.cpu();
  if (sample.has_period())
    sample_info.period = sample.period();
  if (sample.callchain_size() > 0) {
    uint64_t callchain_size = sample.callchain_size();
    sample_info.callchain = reinterpret_cast<struct ip_callchain*>(
        new uint64_t[callchain_size + 1]);
    sample_info.callchain->nr = callchain_size;
    for (size_t i = 0; i < callchain_size; ++i)
      sample_info.callchain->ips[i] = sample.callchain(i);
  }
  if (sample.raw_size() > 0) {
    sample_info.raw_size = sample.raw_size();
    sample_info.raw_data = new uint8_t[sample.raw_size()];
    memset(sample_info.raw_data, 0, sample.raw_size());
  }
  if (sample.branch_stack_size() > 0) {
    uint64_t branch_stack_size = sample.branch_stack_size();
    sample_info.branch_stack =
        reinterpret_cast<struct branch_stack*>(
            new uint8_t[sizeof(uint64_t) +
                        branch_stack_size * sizeof(struct branch_entry)]);
    sample_info.branch_stack->nr = branch_stack_size;
    for (size_t i = 0; i < branch_stack_size; ++i) {
      struct branch_entry& entry = sample_info.branch_stack->entries[i];
      memset(&entry, 0, sizeof(entry));
      entry.from = sample.branch_stack(i).from_ip();
      entry.to = sample.branch_stack(i).to_ip();
      entry.flags.mispred = sample.branch_stack(i).mispredicted();
      entry.flags.predicted = !entry.flags.mispred;
    }
  }

  if (sample.has_weight())
    sample_info.weight = sample.weight();
  if (sample.has_data_src())
    sample_info.data_src = sample.data_src();
  if (sample.has_transaction())
    sample_info.transaction = sample.transaction();

  return WritePerfSampleInfo(sample_info, event);
}

bool PerfSerializer::SerializeMMapSample(
    const event_t& event,
    PerfDataProto_MMapEvent* sample) const {
  const struct mmap_event& mmap = event.mmap;
  sample->set_pid(mmap.pid);
  sample->set_tid(mmap.tid);
  sample->set_start(mmap.start);
  sample->set_len(mmap.len);
  sample->set_pgoff(mmap.pgoff);
  sample->set_filename(mmap.filename);
  sample->set_filename_md5_prefix(Md5Prefix(mmap.filename));

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeMMapSample(
    const PerfDataProto_MMapEvent& sample,
    event_t* event) const {
  struct mmap_event& mmap = event->mmap;
  mmap.pid = sample.pid();
  mmap.tid = sample.tid();
  mmap.start = sample.start();
  mmap.len = sample.len();
  mmap.pgoff = sample.pgoff();
  snprintf(mmap.filename, PATH_MAX, "%s", sample.filename().c_str());

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeMMap2Sample(
    const event_t& event,
    PerfDataProto_MMapEvent* sample) const {
  const struct mmap2_event& mmap = event.mmap2;
  sample->set_pid(mmap.pid);
  sample->set_tid(mmap.tid);
  sample->set_start(mmap.start);
  sample->set_len(mmap.len);
  sample->set_pgoff(mmap.pgoff);
  sample->set_maj(mmap.maj);
  sample->set_min(mmap.min);
  sample->set_ino(mmap.ino);
  sample->set_ino_generation(mmap.ino_generation);
  sample->set_prot(mmap.prot);
  sample->set_flags(mmap.flags);
  sample->set_filename(mmap.filename);
  sample->set_filename_md5_prefix(Md5Prefix(mmap.filename));

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeMMap2Sample(
    const PerfDataProto_MMapEvent& sample,
    event_t* event) const {
  struct mmap2_event& mmap = event->mmap2;
  mmap.pid = sample.pid();
  mmap.tid = sample.tid();
  mmap.start = sample.start();
  mmap.len = sample.len();
  mmap.pgoff = sample.pgoff();
  mmap.maj = sample.maj();
  mmap.min = sample.min();
  mmap.ino = sample.ino();
  mmap.ino_generation = sample.ino_generation();
  mmap.prot = sample.prot();
  mmap.flags = sample.flags();
  snprintf(mmap.filename, PATH_MAX, "%s", sample.filename().c_str());

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeCommSample(
      const event_t& event,
      PerfDataProto_CommEvent* sample) const {
  const struct comm_event& comm = event.comm;
  sample->set_pid(comm.pid);
  sample->set_tid(comm.tid);
  sample->set_comm(comm.comm);
  sample->set_comm_md5_prefix(Md5Prefix(comm.comm));

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeCommSample(
    const PerfDataProto_CommEvent& sample,
    event_t* event) const {
  struct comm_event& comm = event->comm;
  comm.pid = sample.pid();
  comm.tid = sample.tid();
  snprintf(comm.comm, sizeof(comm.comm), "%s", sample.comm().c_str());

  // Sometimes the command string will be modified.  e.g. if the original comm
  // string is not recoverable from the Md5sum prefix, then use the latter as a
  // replacement comm string.  However, if the original was < 8 bytes (fit into
  // |sizeof(uint64_t)|), then the size is no longer correct.  This section
  // checks for the size difference and updates the size in the header.
  uint64_t sample_fields =
      SampleInfoReader::GetSampleFieldsForEventType(comm.header.type,
                                                    sample_type_);
  comm.header.size = SampleInfoReader::GetPerfSampleDataOffset(*event) +
                     GetNumBits(sample_fields) * sizeof(uint64_t);

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeForkExitSample(
    const event_t& event,
    PerfDataProto_ForkEvent* sample) const {
  const struct fork_event& fork = event.fork;
  sample->set_pid(fork.pid);
  sample->set_ppid(fork.ppid);
  sample->set_tid(fork.tid);
  sample->set_ptid(fork.ptid);
  sample->set_fork_time_ns(fork.time);

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeForkExitSample(
    const PerfDataProto_ForkEvent& sample,
    event_t* event) const {
  struct fork_event& fork = event->fork;
  fork.pid = sample.pid();
  fork.ppid = sample.ppid();
  fork.tid = sample.tid();
  fork.ptid = sample.ptid();
  fork.time = sample.fork_time_ns();

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeLostSample(
    const event_t& event,
    PerfDataProto_LostEvent* sample) const {
  const struct lost_event& lost = event.lost;
  sample->set_id(lost.id);
  sample->set_lost(lost.lost);

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeLostSample(
    const PerfDataProto_LostEvent& sample,
    event_t* event) const {
  struct lost_event& lost = event->lost;
  lost.id = sample.id();
  lost.lost = sample.lost();

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeThrottleSample(
    const event_t& event,
    PerfDataProto_ThrottleEvent* sample) const {
  const struct throttle_event& throttle = event.throttle;
  sample->set_time_ns(throttle.time);
  sample->set_id(throttle.id);
  sample->set_stream_id(throttle.stream_id);

  return SerializeSampleInfo(event, sample->mutable_sample_info());
}

bool PerfSerializer::DeserializeThrottleSample(
    const PerfDataProto_ThrottleEvent& sample,
    event_t* event) const {
  struct throttle_event& throttle = event->throttle;
  throttle.time = sample.time_ns();
  throttle.id = sample.id();
  throttle.stream_id = sample.stream_id();

  return DeserializeSampleInfo(sample.sample_info(), event);
}

bool PerfSerializer::SerializeReadSample(
    const event_t& event,
    PerfDataProto_ReadEvent* sample) const {
  const struct read_event& read = event.read;
  sample->set_pid(read.pid);
  sample->set_tid(read.tid);
  sample->set_value(read.value);
  sample->set_time_enabled(read.time_enabled);
  sample->set_time_running(read.time_running);
  sample->set_id(read.id);

  return true;
}

bool PerfSerializer::DeserializeReadSample(
    const PerfDataProto_ReadEvent& sample,
    event_t* event) const {
  struct read_event& read = event->read;
  read.pid = sample.pid();
  read.tid = sample.tid();
  read.value = sample.value();
  read.time_enabled = sample.time_enabled();
  read.time_running = sample.time_running();
  read.id = sample.id();

  return true;
}

bool PerfSerializer::SerializeSampleInfo(
    const event_t& event,
    PerfDataProto_SampleInfo* sample) const {
  perf_sample sample_info;
  if (!ReadPerfSampleInfo(event, &sample_info))
    return false;

  if (sample_type_ & PERF_SAMPLE_TID) {
    sample->set_pid(sample_info.pid);
    sample->set_tid(sample_info.tid);
  }
  if (sample_type_ & PERF_SAMPLE_TIME)
    sample->set_sample_time_ns(sample_info.time);
  if (sample_type_ & PERF_SAMPLE_ID)
    sample->set_id(sample_info.id);
  if (sample_type_ & PERF_SAMPLE_CPU)
    sample->set_cpu(sample_info.cpu);
  return true;
}

bool PerfSerializer::DeserializeSampleInfo(
    const PerfDataProto_SampleInfo& sample,
    event_t* event) const {
  perf_sample sample_info;
  size_t sample_info_size = 0;
  if (sample.has_tid()) {
    sample_info.pid = sample.pid();
    sample_info.tid = sample.tid();
    sample_info_size += sizeof(uint64_t);
  }
  if (sample.has_sample_time_ns()) {
    sample_info.time = sample.sample_time_ns();
    sample_info_size += sizeof(uint64_t);
  }
  if (sample.has_id()) {
    sample_info.id = sample.id();
    sample_info_size += sizeof(uint64_t);
  }
  if (sample.has_cpu()) {
    sample_info.cpu = sample.cpu();
    sample_info_size += sizeof(uint64_t);
  }

  // The event info may have changed (e.g. strings replaced with Md5sum), so
  // adjust the size accordingly.
  event->header.size =
      SampleInfoReader::GetPerfSampleDataOffset(*event) + sample_info_size;

  return WritePerfSampleInfo(sample_info, event);
}

bool PerfSerializer::SerializeTracingMetadata(
    const std::vector<char>& from, PerfDataProto* to) const {
  if (from.empty()) {
    return true;
  }
  PerfDataProto_PerfTracingMetadata* data = to->mutable_tracing_data();
  data->set_tracing_data(from.data(), from.size());
  data->set_tracing_data_md5_prefix(Md5Prefix(from));

  return true;
}

bool PerfSerializer::DeserializeTracingMetadata(
    const PerfDataProto& from, std::vector<char>* to) const {
  if (!from.has_tracing_data()) {
    to->clear();
    return true;
  }

  const PerfDataProto_PerfTracingMetadata &data = from.tracing_data();
  to->assign(data.tracing_data().begin(), data.tracing_data().end());
  return true;
}

bool PerfSerializer::SerializeBuildIDs(
    const std::vector<malloced_unique_ptr<build_id_event>>& from,
    RepeatedPtrField<PerfDataProto_PerfBuildID>* to) const {
  return SerializeBuildIDEvents(from, to);
}

bool PerfSerializer::DeserializeBuildIDs(
    const RepeatedPtrField<PerfDataProto_PerfBuildID>& from,
    std::vector<malloced_unique_ptr<build_id_event>>* to) const {
  to->clear();

  return DeserializeBuildIDEvents(from, to);
}

bool PerfSerializer::SerializeMetadata(PerfDataProto* to) const {
  if (!SerializeTracingMetadata(tracing_data_, to) ||
      !SerializeBuildIDs(build_id_events_, to->mutable_build_ids()) ||
      !SerializeUint32Metadata(uint32_metadata_,
                               to->mutable_uint32_metadata()) ||
      !SerializeUint64Metadata(uint64_metadata_,
                               to->mutable_uint64_metadata()) ||
      !SerializeCPUTopologyMetadata(cpu_topology_,
                                    to->mutable_cpu_topology()) ||
      !SerializeNUMATopologyMetadata(numa_topology_,
                                     to->mutable_numa_topology())) {
    return false;
  }
  typedef PerfDataProto_StringMetadata_StringAndMd5sumPrefix
      StringAndMd5sumPrefix;
  // Handle the string metadata specially.
  for (size_t i = 0; i < string_metadata_.size(); ++i) {
    StringAndMd5sumPrefix* to_metadata = NULL;
    uint32_t type = string_metadata_[i].type;
    PerfDataProto_StringMetadata* proto_string_metadata =
        to->mutable_string_metadata();
    bool is_command_line = false;
    switch (type) {
    case HEADER_HOSTNAME:
      to_metadata = proto_string_metadata->mutable_hostname();
      break;
    case HEADER_OSRELEASE:
      to_metadata = proto_string_metadata->mutable_kernel_version();
      break;
    case HEADER_VERSION:
      to_metadata = proto_string_metadata->mutable_perf_version();
      break;
    case HEADER_ARCH:
      to_metadata = proto_string_metadata->mutable_architecture();
      break;
    case HEADER_CPUDESC:
      to_metadata = proto_string_metadata->mutable_cpu_description();
      break;
    case HEADER_CPUID:
      to_metadata = proto_string_metadata->mutable_cpu_id();
      break;
    case HEADER_CMDLINE:
      is_command_line = true;
      to_metadata = proto_string_metadata->mutable_perf_command_line_whole();
      break;
    default:
      LOG(ERROR) << "Unsupported string metadata type: " << type;
      continue;
    }
    if (is_command_line) {
      // Handle command lines as a special case. It has two protobuf fields, one
      // of which is a repeated field.
      string full_command_line;
      for (size_t j = 0; j < string_metadata_[i].data.size(); ++j) {
        StringAndMd5sumPrefix* command_line_token =
                proto_string_metadata->add_perf_command_line_token();
        command_line_token->set_value(string_metadata_[i].data[j].str);
        command_line_token->
            set_value_md5_prefix(Md5Prefix(command_line_token->value()));
        full_command_line += string_metadata_[i].data[j].str + " ";
      }
      // Delete the extra space at the end of the newly created command string.
      TrimWhitespace(&full_command_line);
      to_metadata->set_value(full_command_line);
      to_metadata->set_value_md5_prefix(Md5Prefix(full_command_line));
    } else {
      DCHECK(to_metadata);  // Make sure a valid destination metadata was found.
      // In some cases there is a null or empty string metadata value in the
      // perf data. Make sure not to access |string_metadata_[i].data[0]| if
      // that is the case.
      if (!string_metadata_[i].data.empty()) {
        to_metadata->set_value(string_metadata_[i].data[0].str);
      } else {
        to_metadata->set_value(string());
      }
      to_metadata->set_value_md5_prefix(Md5Prefix(to_metadata->value()));
    }
  }
  return true;
}

bool PerfSerializer::DeserializeMetadata(const PerfDataProto& from) {
  if (!DeserializeTracingMetadata(from, &tracing_data_) ||
      !DeserializeBuildIDs(from.build_ids(), &build_id_events_) ||
      !DeserializeUint32Metadata(from.uint32_metadata(), &uint32_metadata_) ||
      !DeserializeUint64Metadata(from.uint64_metadata(), &uint64_metadata_) ||
      !DeserializeCPUTopologyMetadata(from.cpu_topology(), &cpu_topology_) ||
      !DeserializeNUMATopologyMetadata(from.numa_topology(), &numa_topology_)) {
    return false;
  }

  // Handle the string metadata specially.
  typedef PerfDataProto_StringMetadata_StringAndMd5sumPrefix
      StringAndMd5sumPrefix;
  const PerfDataProto_StringMetadata& data = from.string_metadata();
  std::vector<std::pair<u32, StringAndMd5sumPrefix> > metadata_strings;
  if (data.has_hostname()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_HOSTNAME), data.hostname()));
  }
  if (data.has_kernel_version()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_OSRELEASE),
                       data.kernel_version()));
  }
  if (data.has_perf_version()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_VERSION), data.perf_version()));
  }
  if (data.has_architecture()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_ARCH), data.architecture()));
  }
  if (data.has_cpu_description()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_CPUDESC),
                       data.cpu_description()));
  }
  if (data.has_cpu_id()) {
    metadata_strings.push_back(
        std::make_pair(static_cast<u32>(HEADER_CPUID), data.cpu_id()));
  }

  // Add each string metadata element to |string_metadata_|.
  for (size_t i = 0; i < metadata_strings.size(); ++i) {
    PerfStringMetadata metadata;
    metadata.type = metadata_strings[i].first;
    CStringWithLength cstring;
    cstring.str = metadata_strings[i].second.value();
    cstring.len = cstring.str.size() + 1;   // Include the null terminator.
    metadata.data.push_back(cstring);

    string_metadata_.push_back(metadata);
  }

  // Add the command line tokens as a special case (repeated field).
  if (data.perf_command_line_token_size() > 0) {
    PerfStringMetadata metadata;
    metadata.type = HEADER_CMDLINE;
    for (int i = 0; i < data.perf_command_line_token_size(); ++i) {
      CStringWithLength cstring;
      cstring.str = data.perf_command_line_token(i).value();
      cstring.len = cstring.str.size() + 1;   // Include the null terminator.
      metadata.data.push_back(cstring);
    }
    string_metadata_.push_back(metadata);
  }

  return true;
}

bool PerfSerializer::SerializeBuildIDEvent(
    const malloced_unique_ptr<build_id_event>& from,
    PerfDataProto_PerfBuildID* to) const {
  to->set_misc(from->header.misc);
  to->set_pid(from->pid);
  to->set_filename(from->filename);
  to->set_filename_md5_prefix(Md5Prefix(from->filename));

  // Trim out trailing zeroes from the build ID.
  string build_id = HexToString(from->build_id, kBuildIDArraySize);
  TrimZeroesFromBuildIDString(&build_id);

  uint8_t build_id_bytes[kBuildIDArraySize];
  if (!StringToHex(build_id, build_id_bytes, sizeof(build_id_bytes)))
    return false;
  // Used to convert build IDs (and possibly other hashes) between raw data
  // format and as string of hex digits.
  const int kHexCharsPerByte = 2;
  to->set_build_id_hash(build_id_bytes, build_id.size() / kHexCharsPerByte);

  return true;
}

bool PerfSerializer::DeserializeBuildIDEvent(
    const PerfDataProto_PerfBuildID& from,
    malloced_unique_ptr<build_id_event>* to) const {
  const string& filename = from.filename();
  size_t size = sizeof(build_id_event) + GetUint64AlignedStringLength(filename);

  malloced_unique_ptr<build_id_event>& event = *to;
  event.reset(CallocMemoryForBuildID(size));
  event->header.type = PERF_RECORD_HEADER_BUILD_ID;
  event->header.size = size;
  event->header.misc = from.misc();
  event->pid = from.pid();
  memcpy(event->build_id, from.build_id_hash().c_str(),
         from.build_id_hash().size());

  if (from.has_filename() && !filename.empty()) {
    CHECK_GT(snprintf(event->filename, filename.size() + 1, "%s",
                      filename.c_str()),
             0);
  }
  return true;
}

bool PerfSerializer::SerializeSingleUint32Metadata(
    const PerfUint32Metadata& metadata,
    PerfDataProto_PerfUint32Metadata* proto_metadata) const {
  proto_metadata->set_type(metadata.type);
  for (size_t i = 0; i < metadata.data.size(); ++i)
    proto_metadata->add_data(metadata.data[i]);
  return true;
}

bool PerfSerializer::DeserializeSingleUint32Metadata(
    const PerfDataProto_PerfUint32Metadata& proto_metadata,
    PerfUint32Metadata* metadata) const {
  metadata->type = proto_metadata.type();
  for (int i = 0; i < proto_metadata.data_size(); ++i)
    metadata->data.push_back(proto_metadata.data(i));
  return true;
}

bool PerfSerializer::SerializeSingleUint64Metadata(
    const PerfUint64Metadata& metadata,
    PerfDataProto_PerfUint64Metadata* proto_metadata) const {
  proto_metadata->set_type(metadata.type);
  for (size_t i = 0; i < metadata.data.size(); ++i)
    proto_metadata->add_data(metadata.data[i]);
  return true;
}

bool PerfSerializer::DeserializeSingleUint64Metadata(
    const PerfDataProto_PerfUint64Metadata& proto_metadata,
    PerfUint64Metadata* metadata) const {
  metadata->type = proto_metadata.type();
  for (int i = 0; i < proto_metadata.data_size(); ++i)
    metadata->data.push_back(proto_metadata.data(i));
  return true;
}

bool PerfSerializer::SerializeCPUTopologyMetadata(
    const PerfCPUTopologyMetadata& metadata,
    PerfDataProto_PerfCPUTopologyMetadata* proto_metadata) const {
  for (size_t i = 0; i < metadata.core_siblings.size(); ++i) {
    const string& str = metadata.core_siblings[i].str;
    proto_metadata->add_core_siblings(str);
    proto_metadata->add_core_siblings_md5_prefix(Md5Prefix(str));
  }

  for (size_t i = 0; i < metadata.thread_siblings.size(); ++i) {
    const string& str = metadata.thread_siblings[i].str;
    proto_metadata->add_thread_siblings(str);
    proto_metadata->add_thread_siblings_md5_prefix(Md5Prefix(str));
  }
  return true;
}

bool PerfSerializer::DeserializeCPUTopologyMetadata(
    const PerfDataProto_PerfCPUTopologyMetadata& proto_metadata,
    PerfCPUTopologyMetadata* metadata) const {
  for (int i = 0; i < proto_metadata.core_siblings_size(); ++i) {
    CStringWithLength core;
    core.str = proto_metadata.core_siblings(i);
    core.len = GetUint64AlignedStringLength(core.str);
    metadata->core_siblings.push_back(core);
  }

  for (int i = 0; i < proto_metadata.thread_siblings_size(); ++i) {
    CStringWithLength thread;
    thread.str = proto_metadata.thread_siblings(i);
    thread.len = GetUint64AlignedStringLength(thread.str);
    metadata->thread_siblings.push_back(thread);
  }
  return true;
}

bool PerfSerializer::SerializeNodeTopologyMetadata(
    const PerfNodeTopologyMetadata& metadata,
    PerfDataProto_PerfNodeTopologyMetadata* proto_metadata) const {
  proto_metadata->set_id(metadata.id);
  proto_metadata->set_total_memory(metadata.total_memory);
  proto_metadata->set_free_memory(metadata.free_memory);
  proto_metadata->set_cpu_list(metadata.cpu_list.str);
  proto_metadata->set_cpu_list_md5_prefix(Md5Prefix(metadata.cpu_list.str));
  return true;
}

bool PerfSerializer::DeserializeNodeTopologyMetadata(
    const PerfDataProto_PerfNodeTopologyMetadata& proto_metadata,
    PerfNodeTopologyMetadata* metadata) const {
  metadata->id = proto_metadata.id();
  metadata->total_memory = proto_metadata.total_memory();
  metadata->free_memory = proto_metadata.free_memory();
  metadata->cpu_list.str = proto_metadata.cpu_list();
  metadata->cpu_list.len = GetUint64AlignedStringLength(metadata->cpu_list.str);
  return true;
}

}  // namespace quipper
