bool ReportCommand::ReadEventAttrFromRecordFile() {
  std::vector<const PerfFileFormat::FileAttr*> attrs = record_file_reader_->AttrSection();
  if (attrs.size() != 1) {
    LOG(ERROR) << "record file contains " << attrs.size() << " attrs";
    return false;
  }
  event_attr_ = attrs[0]->attr;
  if (use_branch_address_ && (event_attr_.sample_type & PERF_SAMPLE_BRANCH_STACK) == 0) {
    LOG(ERROR) << record_filename_ << " is not recorded with branch stack sampling option.";
    return false;
  }
  return true;
}
void DumpRecordCommandImpl::DumpAttrSection() {
  std::vector<const FileAttr*> attrs = record_file_reader_->AttrSection();
  for (size_t i = 0; i < attrs.size(); ++i) {
    auto& attr = attrs[i];
    printf("file_attr %zu:\n", i + 1);
    DumpPerfEventAttr(attr->attr, 1);
    printf("  ids[file_section]: offset %" PRId64 ", size %" PRId64 "\n", attr->ids.offset,
           attr->ids.size);
    std::vector<uint64_t> ids = record_file_reader_->IdsForAttr(attr);
    if (ids.size() > 0) {
      printf("  ids:");
      for (auto& id : ids) {
        printf(" %" PRId64, id);
      }
      printf("\n");
    }
  }
}
void DumpRecordCommand::DumpAttrSection() {
  const std::vector<FileAttr>& attrs = record_file_reader_->AttrSection();
  for (size_t i = 0; i < attrs.size(); ++i) {
    const auto& attr = attrs[i];
    printf("file_attr %zu:\n", i + 1);
    DumpPerfEventAttr(attr.attr, 1);
    printf("  ids[file_section]: offset %" PRId64 ", size %" PRId64 "\n", attr.ids.offset,
           attr.ids.size);
    std::vector<uint64_t> ids;
    if (!record_file_reader_->ReadIdsForAttr(attr, &ids)) {
      return;
    }
    if (!ids.empty()) {
      printf("  ids:");
      for (const auto& id : ids) {
        printf(" %" PRId64, id);
      }
      printf("\n");
    }
  }
}