/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "event_attr.h"

#include <inttypes.h>
#include <stdio.h>
#include <string>
#include <unordered_map>

#include <android-base/logging.h>

#include "event_type.h"
#include "utils.h"

static std::string BitsToString(const std::string& name, uint64_t bits,
                                const std::vector<std::pair<int, std::string>>& bit_names) {
  std::string result;
  for (auto& p : bit_names) {
    if (bits & p.first) {
      bits &= ~p.first;
      if (!result.empty()) {
        result += ", ";
      }
      result += p.second;
    }
  }
  if (bits != 0) {
    LOG(DEBUG) << "unknown " << name << " bits: " << std::hex << bits;
  }
  return result;
}

static std::string SampleTypeToString(uint64_t sample_type) {
  static std::vector<std::pair<int, std::string>> sample_type_names = {
      {PERF_SAMPLE_ADDR, "addr"},
      {PERF_SAMPLE_BRANCH_STACK, "branch_stack"},
      {PERF_SAMPLE_CALLCHAIN, "callchain"},
      {PERF_SAMPLE_CPU, "cpu"},
      {PERF_SAMPLE_ID, "id"},
      {PERF_SAMPLE_IP, "ip"},
      {PERF_SAMPLE_PERIOD, "period"},
      {PERF_SAMPLE_RAW, "raw"},
      {PERF_SAMPLE_READ, "read"},
      {PERF_SAMPLE_REGS_USER, "regs_user"},
      {PERF_SAMPLE_STACK_USER, "stack_user"},
      {PERF_SAMPLE_STREAM_ID, "stream_id"},
      {PERF_SAMPLE_TID, "tid"},
      {PERF_SAMPLE_TIME, "time"},
  };
  return BitsToString("sample_type", sample_type, sample_type_names);
}

static std::string ReadFormatToString(uint64_t read_format) {
  static std::vector<std::pair<int, std::string>> read_format_names = {
      {PERF_FORMAT_TOTAL_TIME_ENABLED, "total_time_enabled"},
      {PERF_FORMAT_TOTAL_TIME_RUNNING, "total_time_running"},
      {PERF_FORMAT_ID, "id"},
      {PERF_FORMAT_GROUP, "group"},
  };
  return BitsToString("read_format", read_format, read_format_names);
}

perf_event_attr CreateDefaultPerfEventAttr(const EventType& event_type) {
  perf_event_attr attr;
  memset(&attr, 0, sizeof(attr));
  attr.size = sizeof(perf_event_attr);
  attr.type = event_type.type;
  attr.config = event_type.config;
  attr.mmap = 1;
  attr.comm = 1;
  attr.disabled = 0;
  // Changing read_format affects the layout of the data read from perf_event_file, namely
  // PerfCounter in event_fd.h.
  attr.read_format =
      PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID;
  attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_PERIOD |
      PERF_SAMPLE_CPU | PERF_SAMPLE_ID;

  if (attr.type == PERF_TYPE_TRACEPOINT) {
    // Tracepoint information are stored in raw data in sample records.
    attr.sample_type |= PERF_SAMPLE_RAW;
  }
  return attr;
}

void DumpPerfEventAttr(const perf_event_attr& attr, size_t indent) {
  std::string event_name = GetEventNameByAttr(attr);
  PrintIndented(indent, "event_attr: for event type %s\n", event_name.c_str());

  PrintIndented(indent + 1, "type %u, size %u, config %llu\n", attr.type, attr.size, attr.config);

  if (attr.freq != 0) {
    PrintIndented(indent + 1, "sample_freq %llu\n", attr.sample_freq);
  } else {
    PrintIndented(indent + 1, "sample_period %llu\n", attr.sample_period);
  }

  PrintIndented(indent + 1, "sample_type (0x%llx) %s\n", attr.sample_type,
                SampleTypeToString(attr.sample_type).c_str());

  PrintIndented(indent + 1, "read_format (0x%llx) %s\n", attr.read_format,
                ReadFormatToString(attr.read_format).c_str());

  PrintIndented(indent + 1, "disabled %u, inherit %u, pinned %u, exclusive %u\n", attr.disabled,
                attr.inherit, attr.pinned, attr.exclusive);

  PrintIndented(indent + 1, "exclude_user %u, exclude_kernel %u, exclude_hv %u\n",
                attr.exclude_user, attr.exclude_kernel, attr.exclude_hv);

  PrintIndented(indent + 1, "exclude_idle %u, mmap %u, comm %u, freq %u\n", attr.exclude_idle,
                attr.mmap, attr.comm, attr.freq);

  PrintIndented(indent + 1, "inherit_stat %u, enable_on_exec %u, task %u\n", attr.inherit_stat,
                attr.enable_on_exec, attr.task);

  PrintIndented(indent + 1, "watermark %u, precise_ip %u, mmap_data %u\n", attr.watermark,
                attr.precise_ip, attr.mmap_data);

  PrintIndented(indent + 1, "sample_id_all %u, exclude_host %u, exclude_guest %u\n",
                attr.sample_id_all, attr.exclude_host, attr.exclude_guest);
  PrintIndented(indent + 1, "branch_sample_type 0x%" PRIx64 "\n", attr.branch_sample_type);
  PrintIndented(indent + 1, "exclude_callchain_kernel %u, exclude_callchain_user %u\n",
                attr.exclude_callchain_kernel, attr.exclude_callchain_user);
  PrintIndented(indent + 1, "sample_regs_user 0x%" PRIx64 "\n", attr.sample_regs_user);
  PrintIndented(indent + 1, "sample_stack_user 0x%" PRIx64 "\n", attr.sample_stack_user);
}

bool GetCommonEventIdPositionsForAttrs(std::vector<perf_event_attr>& attrs,
                                           size_t* event_id_pos_in_sample_records,
                                           size_t* event_id_reverse_pos_in_non_sample_records) {
  // When there are more than one perf_event_attrs, we need to read event id
  // in each record to decide current record should use which attr. So
  // we need to determine the event id position in a record here.
  std::vector<uint64_t> sample_types;
  for (const auto& attr : attrs) {
    sample_types.push_back(attr.sample_type);
  }
  // First determine event_id_pos_in_sample_records.
  // If PERF_SAMPLE_IDENTIFIER is enabled, it is just after perf_event_header.
  // If PERF_SAMPLE_ID is enabled, then PERF_SAMPLE_IDENTIFIER | IP | TID | TIME | ADDR
  // should also be the same.
  bool identifier_enabled = true;
  bool id_enabled = true;
  uint64_t flags_before_id_mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | PERF_SAMPLE_TID |
      PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR;
  uint64_t flags_before_id = sample_types[0] & flags_before_id_mask;
  bool flags_before_id_are_the_same = true;
  for (auto type : sample_types) {
    identifier_enabled &= (type & PERF_SAMPLE_IDENTIFIER) != 0;
    id_enabled &= (type & PERF_SAMPLE_ID) != 0;
    flags_before_id_are_the_same &= (type & flags_before_id_mask) == flags_before_id;
  }
  if (identifier_enabled) {
    *event_id_pos_in_sample_records = sizeof(perf_event_header);
  } else if (id_enabled && flags_before_id_are_the_same) {
    uint64_t pos = sizeof(perf_event_header);
    while (flags_before_id != 0) {
      // Each flags takes 8 bytes in sample records.
      flags_before_id &= flags_before_id - 1;
      pos += 8;
    }
    *event_id_pos_in_sample_records = pos;
  } else {
    LOG(ERROR) << "perf_event_attrs don't have a common event id position in sample records";
    return false;
  }

  // Secondly determine event_id_reverse_pos_in_non_sample_record.
  // If sample_id_all is not enabled, there is no event id in non sample records.
  // If PERF_SAMPLE_IDENTIFIER is enabled, it is at the last 8 bytes of the record.
  // If PERF_SAMPLE_ID is enabled, then PERF_SAMPLE_IDENTIFIER | CPU | STREAM_ID should
  // also be the same.
  bool sample_id_all_enabled = true;
  for (const auto& attr : attrs) {
    if (attr.sample_id_all == 0) {
      sample_id_all_enabled = false;
    }
  }
  if (!sample_id_all_enabled) {
    LOG(ERROR) << "there are perf_event_attrs not enabling sample_id_all, so can't determine "
               << "perf_event_attr for non sample records";
    return false;
  }
  uint64_t flags_after_id_mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID;
  uint64_t flags_after_id = sample_types[0] & flags_after_id_mask;
  bool flags_after_id_are_the_same = true;
  for (auto type : sample_types) {
    flags_after_id_are_the_same &= (type & flags_after_id_mask) == flags_after_id;
  }
  if (identifier_enabled) {
    *event_id_reverse_pos_in_non_sample_records = 8;
  } else if (id_enabled && flags_after_id_are_the_same) {
    uint64_t pos = 8;
    while (flags_after_id != 0) {
      // Each flag takes 8 bytes in sample_id of non sample records.
      flags_after_id &= flags_after_id - 1;
      pos += 8;
    }
    *event_id_reverse_pos_in_non_sample_records = pos;
  } else {
    LOG(ERROR) << "perf_event_attrs don't have a common event id reverse position in non sample records";
    return false;
  }
  return true;
}

bool IsTimestampSupported(const perf_event_attr& attr) {
  return attr.sample_id_all && (attr.sample_type & PERF_SAMPLE_TIME);
}

std::string GetEventNameByAttr(const perf_event_attr& attr) {
  for (const auto& event_type : GetAllEventTypes()) {
    if (event_type.type == attr.type && event_type.config == attr.config) {
      std::string name = event_type.name;
      if (attr.exclude_user && !attr.exclude_kernel) {
        name += ":k";
      } else if (attr.exclude_kernel && !attr.exclude_user) {
        name += ":u";
      }
      return name;
    }
  }
  return "unknown";
}
