// Copyright 2018 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.

#include <string.h>

#include <zircon/syscalls/exception.h>

#include "garnet/bin/debug_agent/arch.h"
#include "garnet/bin/debug_agent/breakpoint.h"
#include "garnet/bin/debug_agent/debugged_thread.h"
#include "garnet/bin/debug_agent/process_breakpoint.h"
#include "garnet/bin/debug_agent/process_memory_accessor.h"
#include "gtest/gtest.h"

namespace debug_agent {

namespace {

// Provides a fake view of memory with the given initial contents.
class FakeMemory : public ProcessMemoryAccessor {
 public:
  FakeMemory(intptr_t address, const char* data, size_t data_len)
      : address_(address) {
    data_.assign(data, data + data_len);
  }

  const char* data() const { return &data_[0]; }

  zx_status_t ReadProcessMemory(uintptr_t address, void* buffer, size_t len,
                                size_t* actual) override {
    *actual = 0;
    if (address < address_ || address + len > address_ + data_.size())
      return ZX_ERR_NO_MEMORY;  // We require everything to be mapped.

    memcpy(buffer, &data_[address - address_], len);
    *actual = len;
    return ZX_OK;
  }

  zx_status_t WriteProcessMemory(uintptr_t address, const void* buffer,
                                 size_t len, size_t* actual) override {
    *actual = 0;
    if (address < address_ || address + len > address_ + data_.size())
      return ZX_ERR_NO_MEMORY;  // We require everything to be mapped.

    memcpy(&data_[address - address_], buffer, len);
    *actual = len;
    return ZX_OK;
  }

 private:
  uintptr_t address_;
  std::vector<char> data_;
};

// Provides a buffer of known memory for tests below.
class BreakpointFakeMemory {
 public:
  // Make a fake memory buffer with enough room to hold a break instruction.
  static constexpr uintptr_t kAddress = 0x123456780;
  static constexpr size_t kDataSize = 4;
  static_assert(kDataSize >= sizeof(arch::BreakInstructionType),
                "Make data bigger for this platform.");
  static const char kOriginalData[kDataSize];

  BreakpointFakeMemory() : memory_(kAddress, kOriginalData, kDataSize) {}
  ~BreakpointFakeMemory() {}

  FakeMemory* memory() { return &memory_; }

  // Returns the memory pointer read out as the type required for the
  // breakpoint instruction.
  arch::BreakInstructionType AsInstructionType() const {
    return *reinterpret_cast<const arch::BreakInstructionType*>(memory_.data());
  }

  // Returns true if the buffer starts with a breakpoint instruction for the
  // current platform.
  bool StartsWithBreak() const {
    return AsInstructionType() == arch::kBreakInstruction;
  }

  // Returns true if the buffer is in its original state.
  bool IsOriginal() const {
    return memcmp(memory_.data(), kOriginalData, kDataSize) == 0;
  }

 private:
  FakeMemory memory_;
};

class FakeProcess : public DebuggedProcess {
 public:
  FakeProcess(zx_koid_t koid)
      : DebuggedProcess(nullptr, koid, zx::process(), true) {}
  ~FakeProcess() = default;

  void AddThread(zx_koid_t koid) {
    threads_[koid] = std::make_unique<DebuggedThread>(
        this, zx::thread(), koid,
        ThreadCreationOption::kSuspendedKeepSuspended);
  }

  DebuggedThread* GetThread(zx_koid_t koid) const override {
    auto it = threads_.find(koid);
    if (it == threads_.end())
      return nullptr;
    return it->second.get();
  }

  std::vector<DebuggedThread*> GetThreads() const override {
    std::vector<DebuggedThread*> threads;
    threads.reserve(threads_.size());
    for (auto& kv : threads_)
      threads.emplace_back(kv.second.get());
    return threads;
  }

 private:
  std::map<zx_koid_t, std::unique_ptr<DebuggedThread>> threads_;
};

// A no-op process delegate.
class TestProcessDelegate : public Breakpoint::ProcessDelegate {
 public:
  TestProcessDelegate() = default;

  BreakpointFakeMemory& mem() { return mem_; }
  std::map<uint64_t, std::unique_ptr<ProcessBreakpoint>>& bps() { return bps_; }

  void InjectFakeProcess(std::unique_ptr<FakeProcess> proc) {
    procs_[proc->koid()] = std::move(proc);
  }

  // This only gets called if Breakpoint.SetSettings() is called.
  zx_status_t RegisterBreakpoint(Breakpoint* bp, zx_koid_t koid,
                                 uint64_t address) override {
    auto found = bps_.find(address);
    if (found == bps_.end()) {
      auto pbp = std::make_unique<ProcessBreakpoint>(bp, procs_[koid].get(),
                                                     mem_.memory(), address);

      zx_status_t status = pbp->Init();
      if (status != ZX_OK) {
        fprintf(stderr, "Failure initializing %d\n", (int)status);
        return status;
      }

      bps_[address] = std::move(pbp);
    } else {
      found->second->RegisterBreakpoint(bp);
    }
    return ZX_OK;
  }
  void UnregisterBreakpoint(Breakpoint* bp, zx_koid_t,
                            uint64_t address) override {
    auto found = bps_.find(address);
    if (found == bps_.end()) {
      GTEST_FAIL();
      return;
    }

    bool still_used = found->second->UnregisterBreakpoint(bp);
    if (!still_used)
      bps_.erase(found);
  }

 private:
  BreakpointFakeMemory mem_;

  std::map<uint64_t, std::unique_ptr<ProcessBreakpoint>> bps_;
  std::map<zx_koid_t, std::unique_ptr<FakeProcess>> procs_;
};

class FakeArchProvider : public arch::ArchProvider {
 public:
  zx_status_t InstallHWBreakpoint(zx::thread* thread,
                                  uint64_t address) override {
    installs_[address]++;
    return ZX_OK;
  }

  zx_status_t UninstallHWBreakpoint(zx::thread* thread,
                                    uint64_t address) override {
    uninstalls_[address]++;
    return ZX_OK;
  }

  size_t InstallCount(uint64_t address) const {
    auto it = installs_.find(address);
    if (it == installs_.end())
      return 0;
    return it->second;
  }
  size_t TotalInstallCalls() const {
    int total = 0;
    for (auto it : installs_) {
      total += it.second;
    }
    return total;
  }

  size_t UninstallCount(uint64_t address) const {
    auto it = uninstalls_.find(address);
    if (it == uninstalls_.end())
      return 0;
    return it->second;
  }
  size_t TotalUninstallCalls() const {
    int total = 0;
    for (auto it : uninstalls_) {
      total += it.second;
    }
    return total;
  }

 private:
  std::map<uint64_t, size_t> installs_;
  std::map<uint64_t, size_t> uninstalls_;
};

class ScopedFakeArchProvider {
 public:
  ScopedFakeArchProvider() {
    auto fake_arch = std::make_unique<FakeArchProvider>();
    fake_arch_ = fake_arch.get();
    arch::ArchProvider::Set(std::move(fake_arch));
  }

  ~ScopedFakeArchProvider() { arch::ArchProvider::Set(nullptr); }

  FakeArchProvider* get() const { return fake_arch_; }

 private:
  FakeArchProvider* fake_arch_;
};

constexpr uintptr_t BreakpointFakeMemory::kAddress;
constexpr size_t BreakpointFakeMemory::kDataSize;
const char
    BreakpointFakeMemory::kOriginalData[BreakpointFakeMemory::kDataSize] = {
        0x01, 0x02, 0x03, 0x04};

}  // namespace

TEST(ProcessBreakpoint, InstallAndFixup) {
  TestProcessDelegate process_delegate;
  Breakpoint main_breakpoint(&process_delegate);
  zx_koid_t process_koid = 0x1234;
  FakeProcess process(process_koid);

  ProcessBreakpoint bp(&main_breakpoint, &process,
                       process_delegate.mem().memory(),
                       BreakpointFakeMemory::kAddress);
  ASSERT_EQ(ZX_OK, bp.Init());

  // Should have written the breakpoint instruction to the buffer.
  EXPECT_TRUE(process_delegate.mem().StartsWithBreak());

  // Make a memory block that contains the address set as the breakpoint.
  // Offset it by kBlockOffset to make sure non-aligned cases are handled.
  debug_ipc::MemoryBlock block;
  constexpr size_t kBlockOffset = 4;
  block.address = BreakpointFakeMemory::kAddress - kBlockOffset;
  block.valid = true;
  block.size = 16;
  block.data.resize(block.size);

  // Fill with current memory contents (including breakpoint instruction).
  memcpy(&block.data[kBlockOffset], process_delegate.mem().memory()->data(),
         BreakpointFakeMemory::kDataSize);

  // FixupMemoryBlock should give back the original data.
  bp.FixupMemoryBlock(&block);
  EXPECT_EQ(
      0, memcmp(&block.data[kBlockOffset], BreakpointFakeMemory::kOriginalData,
                BreakpointFakeMemory::kDataSize));
}

// Attempts to step over the breakpoint from multiple threads at the same
// time.
TEST(ProcessBreakpoint, StepMultiple) {
  TestProcessDelegate process_delegate;
  Breakpoint main_breakpoint(&process_delegate);

  zx_koid_t process_koid = 0x1234;
  FakeProcess process(process_koid);
  ProcessBreakpoint bp(&main_breakpoint, &process,
                       process_delegate.mem().memory(),
                       BreakpointFakeMemory::kAddress);
  ASSERT_EQ(ZX_OK, bp.Init());

  // The breakpoint should be installed.
  EXPECT_TRUE(process_delegate.mem().StartsWithBreak());

  // Begin stepping over the breakpoint from two threads at the same time.
  // The memory should be back to original.
  zx_koid_t kThread1Koid = 1;
  bp.BeginStepOver(kThread1Koid);
  EXPECT_TRUE(process_delegate.mem().IsOriginal());
  zx_koid_t kThread2Koid = 2;
  bp.BeginStepOver(kThread2Koid);
  EXPECT_TRUE(process_delegate.mem().IsOriginal());

  // In real life, the thread would now single-step over the breakpoint. It
  // would trigger a hardware breakpoint at the next instruction.

  EXPECT_TRUE(bp.BreakpointStepHasException(
      kThread1Koid, debug_ipc::NotifyException::Type::kSingleStep));

  // Since one thread is still stepping, the memory should still be original.
  EXPECT_TRUE(process_delegate.mem().IsOriginal());

  // As soon as the second breakpoint is resolved, the breakpoint instruction
  // should be put back.
  EXPECT_TRUE(bp.BreakpointStepHasException(
      kThread2Koid, debug_ipc::NotifyException::Type::kSingleStep));
  EXPECT_TRUE(process_delegate.mem().StartsWithBreak());
}

// This also tests registration and unregistration of ProcessBreakpoints via
// the Breakpoint object.
TEST(ProcessBreakpoint, HitCount) {
  TestProcessDelegate process_delegate;

  constexpr uint32_t kBreakpointId1 = 12;
  debug_ipc::BreakpointSettings settings;
  settings.breakpoint_id = kBreakpointId1;
  settings.locations.resize(1);

  constexpr zx_koid_t kProcess1 = 1;

  debug_ipc::ProcessBreakpointSettings& pr_settings = settings.locations.back();
  pr_settings.process_koid = kProcess1;
  pr_settings.thread_koid = 0;
  pr_settings.address = BreakpointFakeMemory::kAddress;

  // Create a ProcessBreakpoint referencing the two Breakpoint objects
  // (corresponds to two logical breakpoints at the same address).
  std::unique_ptr<Breakpoint> main_breakpoint1 =
      std::make_unique<Breakpoint>(&process_delegate);
  zx_status_t status = main_breakpoint1->SetSettings(settings);
  ASSERT_EQ(ZX_OK, status);

  std::unique_ptr<Breakpoint> main_breakpoint2 =
      std::make_unique<Breakpoint>(&process_delegate);
  constexpr uint32_t kBreakpointId2 = 13;
  settings.breakpoint_id = kBreakpointId2;
  status = main_breakpoint2->SetSettings(settings);
  ASSERT_EQ(ZX_OK, status);

  // There should only be one address with a breakpoint.
  ASSERT_EQ(1u, process_delegate.bps().size());
  EXPECT_EQ(BreakpointFakeMemory::kAddress,
            process_delegate.bps().begin()->first);

  // Hitting the ProcessBreakpoint should update both Breakpoints.
  std::vector<debug_ipc::BreakpointStats> stats;
  process_delegate.bps().begin()->second->OnHit(
      debug_ipc::BreakpointType::kSoftware, &stats);
  ASSERT_EQ(2u, stats.size());

  // Order of the vector is not defined so allow either.
  EXPECT_TRUE((stats[0].breakpoint_id == kBreakpointId1 &&
               stats[1].breakpoint_id == kBreakpointId2) ||
              (stats[0].breakpoint_id == kBreakpointId2 &&
               stats[1].breakpoint_id == kBreakpointId1));

  // The hit count of both should be 1 (order doesn't matter).
  EXPECT_EQ(1u, stats[0].hit_count);
  EXPECT_EQ(1u, stats[1].hit_count);

  // Unregistering one Breakpoint should keep the ProcessBreakpoint.
  main_breakpoint2.reset();
  ASSERT_EQ(1u, process_delegate.bps().size());

  // Unregistering the other should delete it.
  main_breakpoint1.reset();
  ASSERT_EQ(0u, process_delegate.bps().size());
}

TEST(ProcessBreakpoint, HWBreakpointForAllThreads) {
  constexpr zx_koid_t kProcessId = 0x1234;
  constexpr zx_koid_t kThreadId1 = 0x1;
  constexpr zx_koid_t kThreadId2 = 0x2;
  constexpr zx_koid_t kThreadId3 = 0x3;
  constexpr uint32_t kBreakpointId1 = 0x1;
  constexpr uint64_t kAddress = 0x80000000;

  auto process = std::make_unique<FakeProcess>(kProcessId);
  process->AddThread(kThreadId1);
  process->AddThread(kThreadId2);
  process->AddThread(kThreadId3);
  TestProcessDelegate process_delegate;
  process_delegate.InjectFakeProcess(std::move(process));

  // Any calls to the architecture will be routed to this instance.
  ScopedFakeArchProvider arch_provider;

  auto breakpoint = std::make_unique<Breakpoint>(&process_delegate);
  debug_ipc::BreakpointSettings settings1 = {};
  settings1.breakpoint_id = kBreakpointId1;
  settings1.type = debug_ipc::BreakpointType::kHardware;
  // This location is for all threads.
  settings1.locations.push_back({kProcessId, 0, kAddress});
  zx_status_t status = breakpoint->SetSettings(settings1);
  ASSERT_EQ(status, ZX_OK);

  // Should have installed the breakpoint.
  ASSERT_EQ(process_delegate.bps().size(), 1u);
  auto& process_bp = process_delegate.bps().begin()->second;
  ASSERT_EQ(process_bp->address(), kAddress);

  // It should have installed a HW breakpoint for each thread.
  EXPECT_FALSE(process_bp->SoftwareBreakpointInstalled());
  EXPECT_TRUE(process_bp->HardwareBreakpointInstalled());
  EXPECT_EQ(arch_provider.get()->InstallCount(kAddress), 3u);

  // Deleting the breakpoint should remove the process breakpoint.
  breakpoint.reset();
  EXPECT_EQ(arch_provider.get()->UninstallCount(kAddress), 3u);
  EXPECT_EQ(process_delegate.bps().size(), 0u);
}

TEST(ProcessBreakpoint, HWBreakpointWithThreadId) {
  constexpr zx_koid_t kProcessId = 0x1234;
  constexpr zx_koid_t kThreadId1 = 0x1;
  constexpr zx_koid_t kThreadId2 = 0x2;
  constexpr zx_koid_t kThreadId3 = 0x3;
  constexpr uint32_t kBreakpointId1 = 0x1;
  constexpr uint32_t kBreakpointId2 = 0x2;
  constexpr uint32_t kSwBreakpointId = 0x3;
  constexpr uint64_t kAddress = BreakpointFakeMemory::kAddress;
  constexpr uint64_t kOtherAddress = 0x8fffffff;

  auto process = std::make_unique<FakeProcess>(kProcessId);
  process->AddThread(kThreadId1);
  process->AddThread(kThreadId2);
  process->AddThread(kThreadId3);
  TestProcessDelegate process_delegate;
  process_delegate.InjectFakeProcess(std::move(process));

  // Any calls to the architecture will be routed to this instance.
  ScopedFakeArchProvider arch_provider;

  auto breakpoint1 = std::make_unique<Breakpoint>(&process_delegate);
  debug_ipc::BreakpointSettings settings1 = {};
  settings1.breakpoint_id = kBreakpointId1;
  settings1.type = debug_ipc::BreakpointType::kHardware;
  settings1.locations.push_back({kProcessId, kThreadId1, kAddress});
  zx_status_t status = breakpoint1->SetSettings(settings1);
  ASSERT_EQ(status, ZX_OK);
  // Should have installed the process breakpoint.
  ASSERT_EQ(process_delegate.bps().size(), 1u);
  auto& process_bp = process_delegate.bps().begin()->second;
  ASSERT_EQ(process_bp->address(), kAddress);
  // This should have installed HW breakpoint for only one thread.
  // This should have installed only a HW breakpoint.
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 1u);
  ASSERT_EQ(arch_provider.get()->InstallCount(kAddress), 1u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 0u);
  EXPECT_FALSE(process_bp->SoftwareBreakpointInstalled());
  EXPECT_TRUE(process_bp->HardwareBreakpointInstalled());

  // Register another breakpoint.
  auto breakpoint2 = std::make_unique<Breakpoint>(&process_delegate);
  debug_ipc::BreakpointSettings settings2 = {};
  settings2.breakpoint_id = kBreakpointId2;
  settings2.type = debug_ipc::BreakpointType::kHardware;
  settings2.locations.push_back({kProcessId, kThreadId2, kAddress});
  // This breakpoint has another location for another thread.
  // In practice, this should not happen, but it's important that no HW
  // breakpoint get installed if for the wrong location.
  settings2.locations.push_back({kProcessId, kThreadId3, kOtherAddress});
  breakpoint2->SetSettings(settings2);
  // Registering this breakpoint should create a new ProcessBreakpoint.
  ASSERT_EQ(process_delegate.bps().size(), 2u);
  auto& process_bp2 = (process_delegate.bps().begin()++)->second;
  ASSERT_EQ(process_bp2->address(), kOtherAddress);
  // Registering the second breakpoint should install for the new thread in
  // the old location and one in the new location.
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->InstallCount(kAddress), 2u);
  ASSERT_EQ(arch_provider.get()->InstallCount(kOtherAddress), 1u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 0u);
  EXPECT_FALSE(process_bp->SoftwareBreakpointInstalled());

  // Unregistering a breakpoint should only uninstall the HW breakpoint for
  // one thread.
  breakpoint1.reset();
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 1u);
  ASSERT_EQ(arch_provider.get()->UninstallCount(kAddress), 1u);
  ASSERT_EQ(arch_provider.get()->UninstallCount(kOtherAddress), 0u);
  EXPECT_FALSE(process_bp->SoftwareBreakpointInstalled());
  EXPECT_FALSE(process_bp->SoftwareBreakpointInstalled());
  EXPECT_TRUE(process_bp->HardwareBreakpointInstalled());
  EXPECT_TRUE(process_bp2->HardwareBreakpointInstalled());

  // Adding a SW breakpoint should not install HW locations.
  auto sw_breakpoint = std::make_unique<Breakpoint>(&process_delegate);
  debug_ipc::BreakpointSettings sw_settings = {};
  sw_settings.breakpoint_id = kSwBreakpointId;
  sw_settings.type = debug_ipc::BreakpointType::kSoftware;
  sw_settings.locations.push_back({kProcessId, 0, kAddress});
  sw_breakpoint->SetSettings(sw_settings);
  // Should have installed only a SW breakpoint.
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 1u);
  EXPECT_TRUE(process_bp->SoftwareBreakpointInstalled());

  // Unregistering should remove the other hw breakpoint.
  // And also the second process breakpoint.
  breakpoint2.reset();
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->UninstallCount(kAddress), 2u);
  ASSERT_EQ(arch_provider.get()->UninstallCount(kOtherAddress), 1u);
  EXPECT_FALSE(process_bp->HardwareBreakpointInstalled());
  EXPECT_TRUE(process_bp->SoftwareBreakpointInstalled());
  ASSERT_EQ(process_delegate.bps().size(), 1u);
  EXPECT_EQ(process_delegate.bps().begin()->second->address(), kAddress);

  // Removing the SW breakpoint should work and would delete the final process
  // breakpoint.
  sw_breakpoint.reset();
  ASSERT_EQ(arch_provider.get()->TotalInstallCalls(), 3u);
  ASSERT_EQ(arch_provider.get()->TotalUninstallCalls(), 3u);
  EXPECT_EQ(process_delegate.bps().size(), 0u);
}

}  // namespace debug_agent
