// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(dje): wip wip wip

#include "control.h"

#include <fcntl.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cinttypes>

#include <iostream>

#include <lib/zircon-internal/device/cpu-trace/intel-pt.h>
#include <zircon/device/ktrace.h>
#include <zircon/syscalls.h>

#include <lib/fdio/util.h>
#include <lib/zircon-internal/ktrace.h>
#include <lib/zx/handle.h>
#include <lib/zx/vmo.h>

#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_printf.h"

#include "garnet/lib/debugger_utils/util.h"
#include "garnet/lib/debugger_utils/x86_pt.h"

#include "garnet/lib/inferior_control/arch.h"
#include "garnet/lib/inferior_control/arch_x86.h"

#include "server.h"

namespace insntrace {

static constexpr char ipt_device_path[] = "/dev/sys/cpu-trace/insntrace";
static constexpr char ktrace_device_path[] = "/dev/misc/ktrace";

static constexpr char buffer_output_path_suffix[] = "pt";
static constexpr char ktrace_output_path_suffix[] = "ktrace";
static constexpr char cpuid_output_path_suffix[] = "cpuid";
static constexpr char pt_list_output_path_suffix[] = "ptlist";

static constexpr uint32_t kKtraceGroupMask = KTRACE_GRP_ARCH | KTRACE_GRP_TASKS;

static bool OpenDevices(fxl::UniqueFD* out_ipt_fd, fxl::UniqueFD* out_ktrace_fd,
                        zx::handle* out_ktrace_handle) {
  int ipt_fd = -1;
  int ktrace_fd = -1;
  zx_handle_t ktrace_handle = ZX_HANDLE_INVALID;

  if (out_ipt_fd) {
    ipt_fd = open(ipt_device_path, O_RDONLY);
    if (ipt_fd < 0) {
      FXL_LOG(ERROR) << "unable to open " << ipt_device_path << ": "
                     << debugger_utils::ErrnoString(errno);
      return false;
    }
  }

  if (out_ktrace_fd || out_ktrace_handle) {
    ktrace_fd = open(ktrace_device_path, O_RDONLY);
    if (ktrace_fd < 0) {
      FXL_LOG(ERROR) << "open ktrace"
                     << ", " << debugger_utils::ErrnoString(errno);
      close(ipt_fd);
      return false;
    }
  }

  if (out_ktrace_handle) {
    ssize_t ssize = ioctl_ktrace_get_handle(ktrace_fd, &ktrace_handle);
    if (ssize != sizeof(ktrace_handle)) {
      FXL_LOG(ERROR) << "get ktrace handle"
                     << ", " << debugger_utils::ErrnoString(errno);
      close(ipt_fd);
      close(ktrace_fd);
      return false;
    }
  }

  if (out_ipt_fd) {
    out_ipt_fd->reset(ipt_fd);
  }
  if (out_ktrace_fd) {
    out_ktrace_fd->reset(ktrace_fd);
  } else if (ktrace_fd != -1) {
    // Only needed to get ktrace handle.
    close(ktrace_fd);
  }
  if (out_ktrace_handle) {
    out_ktrace_handle->reset(ktrace_handle);
  }

  return true;
}

bool AllocTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "AllocTrace called";

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return false;

  ioctl_insntrace_trace_config_t trace_config;
  trace_config.mode = config.mode;
  trace_config.num_traces = (config.mode == IPT_MODE_CPUS
                             ? config.num_cpus
                             : config.max_threads);
  ssize_t ssize = ioctl_insntrace_alloc_trace(ipt_fd.get(), &trace_config);
  if (ssize < 0) {
    FXL_LOG(ERROR) << "set perf mode: " << debugger_utils::ZxErrorString(ssize);
    goto Fail;
  }

  return true;

Fail:
  return false;
}

static void InitIptBufferConfig(ioctl_insntrace_buffer_config_t* ipt_config,
                                const IptConfig& config) {
  memset(ipt_config, 0, sizeof(*ipt_config));
  ipt_config->num_chunks = config.num_chunks;
  ipt_config->chunk_order = config.chunk_order;
  ipt_config->is_circular = config.is_circular;
  ipt_config->ctl = config.CtlMsr();
  ipt_config->cr3_match = config.cr3_match;
  ipt_config->addr_ranges[0].a = config.AddrBegin(0);
  ipt_config->addr_ranges[0].b = config.AddrEnd(0);
  ipt_config->addr_ranges[1].a = config.AddrBegin(1);
  ipt_config->addr_ranges[1].b = config.AddrEnd(1);
}

bool InitTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "InitTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_CPUS);

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return false;

  for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
    ioctl_insntrace_buffer_config_t ipt_config;
    InitIptBufferConfig(&ipt_config, config);

    uint32_t descriptor;
    auto ssize = ioctl_insntrace_alloc_buffer(ipt_fd.get(), &ipt_config, &descriptor);
    if (ssize < 0) {
      FXL_LOG(ERROR) << "init cpu perf: "
                     << debugger_utils::ZxErrorString(ssize);
      goto Fail;
    }
    // Buffers are automagically assigned to cpus, descriptor == cpu#,
    // so we can just ignore descriptor here.
  }

  return true;

Fail:
  return false;
}

bool InitThreadTrace(inferior_control::Thread* thread, const IptConfig& config) {
  FXL_LOG(INFO) << "InitThreadTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_THREADS);

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return false;

  ioctl_insntrace_buffer_config_t ipt_config;
  InitIptBufferConfig(&ipt_config, config);

  uint32_t descriptor;
  ssize_t ssize =
      ioctl_insntrace_alloc_buffer(ipt_fd.get(), &ipt_config, &descriptor);
  if (ssize < 0) {
    FXL_LOG(ERROR) << "init thread perf: "
                   << debugger_utils::ZxErrorString(ssize);
    goto Fail;
  }

  thread->set_ipt_buffer(descriptor);
  return true;

Fail:
  return false;
}

// This must be called before a process is started so we emit a ktrace
// process start record for it.

bool InitProcessTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "InitProcessTrace called";

  zx::handle ktrace_handle;
  zx_status_t status;

  if (!OpenDevices(nullptr, nullptr, &ktrace_handle))
    return false;

    // If tracing cpus we may want all the records for processes that were
    // started during boot, so don't reset ktrace here. If tracing threads it
    // doesn't much matter other than hopefully the necessary records don't get
    // over run, which is handled below by only enabling the collection groups
    // we need. So for now leave existing records alone.
    // We also need to make the distinction of ktrace records for processes
    // started during boot (they can appear a fair bit in traces), and random
    // processes that were started later that have nothing to do with what we
    // want to collect. IWBN to capture the ktrace records from boot and save
    // them away. Then it'd make more sense to rewind here, though even then
    // the user may have started something important before we get run. Another
    // thought is to provide an action to control ktrace specifically.
#if 0  // TODO(dje)
  if (config.mode == IPT_MODE_THREADS) {
    status = zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_STOP, 0,
                               nullptr);
    if (status != ZX_OK) {
      FXL_LOG(ERROR) << "ktrace stop: " << debugger_utils::ZxErrorString(status);
      goto Fail;
    }
    status = zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_REWIND, 0,
                               nullptr);
    if (status != ZX_OK) {
      FXL_LOG(ERROR) << "ktrace rewind: " << debugger_utils::ZxErrorString(status);
      goto Fail;
    }
  }
#endif

  // We definitely need ktrace turned on in order to get cr3->pid mappings,
  // which we need to map trace cr3 values to ld.so mappings, which we need in
  // order to be able to find the ELFs, which are required by the decoder.
  // So this isn't a nice-to-have, we need it. It's possible ktrace is
  // currently off, so ensure it's turned on.
  // For now just include arch info in the ktrace - we need it, and we don't
  // want to risk the ktrace buffer filling without it.
  // Also include task info to get process exit records - we need to know when
  // a cr3 value becomes invalid. Hopefully this won't cause the buffer to
  // overrun. It it does we could consider having special ktrace records just
  // for this, but that's a last resort kind of thing.
  status = zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_START,
                             kKtraceGroupMask, nullptr);
  if (status != ZX_OK) {
    FXL_LOG(ERROR) << "ktrace start: " << debugger_utils::ZxErrorString(status);
    goto Fail;
  }

  return true;

Fail:
  // TODO(dje): Resume original ktracing? Need ability to get old value.
  // For now set the values to what we need: A later run might still need
  // the boot time records.
  zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_STOP, 0, nullptr);
  zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_START, kKtraceGroupMask,
                    nullptr);

  return false;
}

bool StartTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "StartTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_CPUS);

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return false;

  ssize_t ssize = ioctl_insntrace_start(ipt_fd.get());
  if (ssize < 0) {
    FXL_LOG(ERROR) << "start cpu perf: "
                   << debugger_utils::ZxErrorString(ssize);
    return false;
  }

  return true;
}

bool StartThreadTrace(inferior_control::Thread* thread,
                     const IptConfig& config) {
  FXL_LOG(INFO) << "StartThreadTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_THREADS);

  if (thread->ipt_buffer() < 0) {
    FXL_LOG(INFO) << fxl::StringPrintf("Thread %" PRIu64 " has no IPT buffer",
                                       thread->id());
    // TODO(dje): For now. This isn't an error in the normal sense.
    return true;
  }

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return false;

  ioctl_insntrace_assign_thread_buffer_t assign;
  zx_status_t status;
  ssize_t ssize;

  status = zx_handle_duplicate(thread->handle(), ZX_RIGHT_SAME_RIGHTS,
                               &assign.thread);
  if (status != ZX_OK) {
    FXL_LOG(ERROR) << "duplicating thread handle: "
                   << debugger_utils::ZxErrorString(status);
    goto Fail;
  }
  assign.descriptor = thread->ipt_buffer();
  ssize = ioctl_insntrace_assign_thread_buffer(ipt_fd.get(), &assign);
  if (ssize < 0) {
    FXL_LOG(ERROR) << "assigning ipt buffer to thread: "
                   << debugger_utils::ZxErrorString(ssize);
    goto Fail;
  }

  return true;

Fail:
  return false;
}

void StopTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "StopTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_CPUS);

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return;

  ssize_t ssize = ioctl_insntrace_stop(ipt_fd.get());
  if (ssize < 0) {
    // TODO(dje): This is really bad, this shouldn't fail.
    FXL_LOG(ERROR) << "stop cpu perf: " << debugger_utils::ZxErrorString(ssize);
  }
}

void StopThreadTrace(inferior_control::Thread* thread, const IptConfig& config) {
  FXL_LOG(INFO) << "StopThreadTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_THREADS);

  if (thread->ipt_buffer() < 0) {
    FXL_LOG(INFO) << fxl::StringPrintf("Thread %" PRIu64 " has no IPT buffer",
                                       thread->id());
    return;
  }

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return;

  ioctl_insntrace_assign_thread_buffer_t assign;
  zx_handle_t status;
  ssize_t ssize;

  status = zx_handle_duplicate(thread->handle(), ZX_RIGHT_SAME_RIGHTS,
                               &assign.thread);
  if (status != ZX_OK) {
    FXL_LOG(ERROR) << "duplicating thread handle: "
                   << debugger_utils::ZxErrorString(status);
    goto Fail;
  }
  assign.descriptor = thread->ipt_buffer();
  ssize = ioctl_insntrace_release_thread_buffer(ipt_fd.get(), &assign);
  if (ssize < 0) {
    FXL_LOG(ERROR) << "releasing ipt buffer from thread: "
                   << debugger_utils::ZxErrorString(ssize);
    goto Fail;
  }

Fail:;  // nothing to do
}

void StopSidebandDataCollection(const IptConfig& config) {
  FXL_LOG(INFO) << "StopSidebandDataCollection called";

  zx::handle ktrace_handle;
  if (!OpenDevices(nullptr, nullptr, &ktrace_handle))
    return;

  // Avoid having the records we need overrun by the time we collect them by
  // stopping ktrace here. It will get turned back on by "reset".
  zx_status_t status =
      zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_STOP, 0, nullptr);
  if (status != ZX_OK) {
    // TODO(dje): This shouldn't fail either, should it?
    FXL_LOG(ERROR) << "stop ktrace: " << debugger_utils::ZxErrorString(status);
  }
}

static std::string GetCpuPtFileName(const std::string& output_path_prefix,
                                    uint64_t id) {
  const char* name_prefix = "cpu";
  return fxl::StringPrintf("%s.%s%" PRIu64 ".%s", output_path_prefix.c_str(),
                           name_prefix, id, buffer_output_path_suffix);
}

static std::string GetThreadPtFileName(const std::string& output_path_prefix,
                                       uint64_t id) {
  const char* name_prefix = "thr";
  return fxl::StringPrintf("%s.%s%" PRIu64 ".%s", output_path_prefix.c_str(),
                           name_prefix, id, buffer_output_path_suffix);
}

// Write the contents of buffer |descriptor| to a file.
// The file's name is $output_path_prefix.$name_prefix$id.pt.

static zx_status_t WriteBufferData(const IptConfig& config,
                                   const fxl::UniqueFD& ipt_fd,
                                   uint32_t descriptor, uint64_t id) {
  std::string output_path;
  if (config.mode == IPT_MODE_CPUS)
    output_path = GetCpuPtFileName(config.output_path_prefix, id);
  else
    output_path = GetThreadPtFileName(config.output_path_prefix, id);
  const char* c_path = output_path.c_str();

  zx_status_t status = ZX_OK;

  // Refetch the buffer config as we can be invoked in a separate process,
  // after tracing has started, and shouldn't rely on what the user thinks
  // the config is.
  ioctl_insntrace_buffer_config_t buffer_config;
  ssize_t ssize =
      ioctl_insntrace_get_buffer_config(ipt_fd.get(), &descriptor, &buffer_config);
  if (ssize < 0) {
    FXL_LOG(ERROR) << fxl::StringPrintf(
                          "ioctl_insntrace_get_buffer_config: buffer %u: ",
                          descriptor)
                   << debugger_utils::ZxErrorString(ssize);
    return ssize;
  }

  ioctl_insntrace_buffer_info_t info;
  ssize = ioctl_insntrace_get_buffer_info(ipt_fd.get(), &descriptor, &info);
  if (ssize < 0) {
    FXL_LOG(ERROR) << fxl::StringPrintf(
                          "ioctl_insntrace_get_buffer_info: buffer %u: ", descriptor)
                   << debugger_utils::ZxErrorString(ssize);
    return ssize;
  }

  fxl::UniqueFD fd(open(c_path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR));
  if (!fd.is_valid()) {
    FXL_LOG(ERROR) << fxl::StringPrintf("unable to write file: %s", c_path)
                   << ", " << debugger_utils::ErrnoString(errno);
    return ZX_ERR_BAD_PATH;
  }

  // TODO(dje): Fetch from vmo?
  size_t chunk_size = (1 << buffer_config.chunk_order) * PAGE_SIZE;
  uint32_t num_chunks = buffer_config.num_chunks;

  // If using a circular buffer there's (currently) no way to know if
  // tracing wrapped, so for now we just punt and always dump the entire
  // buffer. It's highly likely it wrapped anyway.
  size_t bytes_left;
  if (buffer_config.is_circular)
    bytes_left = num_chunks * chunk_size;
  else
    bytes_left = info.capture_end;

  FXL_LOG(INFO) << fxl::StringPrintf("Writing %zu bytes to %s", bytes_left,
                                     c_path);

  char buf[4096];

  for (uint32_t i = 0; i < num_chunks && bytes_left > 0; ++i) {
    ioctl_insntrace_chunk_handle_req_t handle_rqst;
    handle_rqst.descriptor = descriptor;
    handle_rqst.chunk_num = i;
    zx_handle_t vmo_handle;
    ssize = ioctl_insntrace_get_chunk_handle(ipt_fd.get(), &handle_rqst, &vmo_handle);
    if (ssize < 0) {
      FXL_LOG(ERROR)
          << fxl::StringPrintf(
                 "ioctl_insntrace_get_buffer_handle: buffer %u, buffer %u: ",
                 descriptor, i)
          << debugger_utils::ZxErrorString(ssize);
      goto Fail;
    }
    zx::vmo vmo(vmo_handle);

    size_t buffer_remaining = chunk_size;
    size_t offset = 0;
    while (buffer_remaining && bytes_left) {
      size_t to_write = sizeof(buf);
      if (to_write > buffer_remaining)
        to_write = buffer_remaining;
      if (to_write > bytes_left)
        to_write = bytes_left;
      // TODO(dje): Mapping into process and reading directly from that
      // left for another day.
      status = vmo.read(buf, offset, to_write);
      if (status != ZX_OK) {
        FXL_LOG(ERROR) << fxl::StringPrintf(
                              "zx_vmo_read: buffer %u, buffer %u, offset %zu: ",
                              descriptor, i, offset)
                       << debugger_utils::ZxErrorString(status);
        goto Fail;
      }
      if (write(fd.get(), buf, to_write) != (ssize_t)to_write) {
        FXL_LOG(ERROR) << fxl::StringPrintf("short write, file: %s\n", c_path);
        status = ZX_ERR_IO;
        goto Fail;
      }
      offset += to_write;
      buffer_remaining -= to_write;
      bytes_left -= to_write;
    }
  }

  assert(bytes_left == 0);
  status = ZX_OK;
  // fallthrough

Fail:
  // We don't delete the file on failure on purpose, it is kept for
  // debugging purposes.
  return status;
}

// Write all output files.
// This assumes tracing has already been stopped.

void DumpTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "DumpTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_CPUS);

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return;

  for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
    // Buffer descriptors for cpus is the cpu number.
    auto status = WriteBufferData(config, ipt_fd, cpu, cpu);
    if (status != ZX_OK) {
      FXL_LOG(ERROR) << fxl::StringPrintf("dump perf of cpu %u: ", cpu)
                     << debugger_utils::ZxErrorString(status);
      // Keep trying to dump other cpu's data.
    }
  }
}

// Write the buffer contents for |thread|.
// This assumes the thread is stopped.

void DumpThreadTrace(inferior_control::Thread* thread, const IptConfig& config) {
  FXL_LOG(INFO) << "DumpThreadTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_THREADS);

  zx_koid_t id = thread->id();

  if (thread->ipt_buffer() < 0) {
    FXL_LOG(INFO) << fxl::StringPrintf("Thread %" PRIu64 " has no IPT buffer",
                                       id);
    return;
  }

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return;

  auto status = WriteBufferData(config, ipt_fd, thread->ipt_buffer(), id);
  if (status != ZX_OK) {
    FXL_LOG(ERROR) << fxl::StringPrintf("dump perf of thread %" PRIu64 ": ", id)
                   << debugger_utils::ZxErrorString(status);
  }
}

void DumpSidebandData(const IptConfig& config) {
  FXL_LOG(INFO) << "DumpSidebandData called";

  {
    fxl::UniqueFD ktrace_fd;
    if (!OpenDevices(nullptr, &ktrace_fd, nullptr))
      return;

    std::string ktrace_output_path = fxl::StringPrintf(
        "%s.%s", config.output_path_prefix.c_str(), ktrace_output_path_suffix);
    const char* ktrace_c_path = ktrace_output_path.c_str();

    fxl::UniqueFD dest_fd(
        open(ktrace_c_path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR));
    if (dest_fd.is_valid()) {
      ssize_t count;
      char buf[1024];
      while ((count = read(ktrace_fd.get(), buf, sizeof(buf))) != 0) {
        if (write(dest_fd.get(), buf, count) != count) {
          FXL_LOG(ERROR) << "error writing " << ktrace_c_path;
        }
      }
    } else {
      FXL_LOG(ERROR) << fxl::StringPrintf("unable to create %s", ktrace_c_path)
                     << ", " << debugger_utils::ErrnoString(errno);
    }
  }

  // TODO(dje): UniqueFILE?
  {
    std::string cpuid_output_path = fxl::StringPrintf(
        "%s.%s", config.output_path_prefix.c_str(), cpuid_output_path_suffix);
    const char* cpuid_c_path = cpuid_output_path.c_str();

    FILE* f = fopen(cpuid_c_path, "w");
    if (f != nullptr) {
      inferior_control::DumpArch(f);
      // Also put the mtc_freq value in the cpuid file, it's as good a place
      // for it as any. See intel-pt.h:pt_config.
      // Alternatively this could be added to the ktrace record.
      // TODO(dje): Put constants in zircon/device/intel-pt.h.
      unsigned mtc_freq = config.mtc_freq;
      fprintf(f, "mtc_freq: %u\n", mtc_freq);
      // TODO(dje): verify writes succeed
      fclose(f);
    } else {
      FXL_LOG(ERROR) << "unable to write PT config to " << cpuid_c_path;
    }
  }

  // TODO(dje): UniqueFILE?
  // TODO(dje): Handle IPT_MODE_THREADS
  if (config.mode == IPT_MODE_CPUS) {
    std::string pt_list_output_path = fxl::StringPrintf(
        "%s.%s", config.output_path_prefix.c_str(), pt_list_output_path_suffix);
    const char* pt_list_c_path = pt_list_output_path.c_str();

    FILE* f = fopen(pt_list_c_path, "w");
    if (f != nullptr) {
      for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
        std::string pt_file = GetCpuPtFileName(config.output_path_prefix, cpu);
        fprintf(f, "%u %s\n", cpu, pt_file.c_str());
      }
      // TODO(dje): verify writes succeed
      fclose(f);
    } else {
      FXL_LOG(ERROR) << "unable to write PT list to " << pt_list_c_path;
    }
  }
}

void ResetTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "ResetTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_CPUS);

  // TODO(dje): Nothing to do currently. There use to be. So keep this
  // function around for a bit.
}

void ResetThreadTrace(inferior_control::Thread* thread,
                     const IptConfig& config) {
  FXL_LOG(INFO) << "ResetThreadTrace called";
  FXL_DCHECK(config.mode == IPT_MODE_THREADS);

  if (thread->ipt_buffer() < 0) {
    FXL_LOG(INFO) << fxl::StringPrintf("Thread %" PRIu64 " has no IPT buffer",
                                       thread->id());
    return;
  }

  fxl::UniqueFD ipt_fd;
  if (!OpenDevices(&ipt_fd, nullptr, nullptr))
    return;

  uint32_t descriptor = thread->ipt_buffer();
  ssize_t ssize = ioctl_insntrace_free_buffer(ipt_fd.get(), &descriptor);
  if (ssize < 0) {
    FXL_LOG(ERROR) << "freeing ipt buffer: "
                   << debugger_utils::ZxErrorString(ssize);
    goto Fail;
  }

Fail:
  thread->set_ipt_buffer(-1);
}

// Free all resources associated with the true.
// This means restoring ktrace to its original state.
// This assumes tracing has already been stopped.

void FreeTrace(const IptConfig& config) {
  FXL_LOG(INFO) << "FreeTrace called";

  fxl::UniqueFD ipt_fd;
  zx::handle ktrace_handle;
  if (!OpenDevices(&ipt_fd, nullptr, &ktrace_handle))
    return;

  ssize_t ssize = ioctl_insntrace_free_trace(ipt_fd.get());
  if (ssize < 0) {
    FXL_LOG(ERROR) << "ioctl_insntrace_free_trace failed: "
                   << debugger_utils::ZxErrorString(ssize);
  }

  // TODO(dje): Resume original ktracing? Need ability to get old value.
  // For now set the values to what we need: A later run might still need
  // the boot time records.
  zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_STOP, 0, nullptr);
#if 0  // TODO(dje): See rewind comments in InitProcessTrace.
  zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_REWIND, 0, nullptr);
#endif
  zx_ktrace_control(ktrace_handle.get(), KTRACE_ACTION_START, kKtraceGroupMask,
                    nullptr);
}

}  // namespace insntrace
