// Copyright 2021 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 "src/developer/debug/zxdb/client/minidump_memory.h"

#include <memory>

#include "src/developer/debug/zxdb/client/elf_memory_region.h"
#include "src/developer/debug/zxdb/client/file_memory_region.h"
#include "src/lib/elflib/elflib.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/unwinder/module.h"

namespace zxdb {

namespace {

// Helper to make crashpad::MemorySnapshot::Read easier to use.
bool ReadMinidumpMemorySnapshot(const crashpad::MemorySnapshot& memory,
                                std::function<bool(void*, size_t)> callback) {
  class Delegate : public crashpad::MemorySnapshot::Delegate {
   public:
    explicit Delegate(std::function<bool(void*, size_t)> cb) : cb_(std::move(cb)) {}
    bool MemorySnapshotDelegateRead(void* data, size_t size) override { return cb_(data, size); }
    std::function<bool(void*, size_t)> cb_;
  };
  Delegate delegate(std::move(callback));
  return memory.Read(&delegate);
}

}  // namespace

MinidumpMemory::MinidumpMemory(const crashpad::ProcessSnapshotMinidump& minidump,
                               BuildIDIndex& build_id_index) {
  for (const auto& thread : minidump.Threads()) {
    auto stack = thread->Stack();

    if (!stack) {
      continue;
    }

    regions_.emplace_back(stack->Address(), stack->Address() + stack->Size(),
                          std::make_shared<SnapshotMemoryRegion>(stack));
  }

  for (const auto& minidump_mod : minidump.Modules()) {
    uint64_t base = minidump_mod->Address();
    auto entry = build_id_index.EntryForBuildID(MinidumpGetBuildId(*minidump_mod));
    std::optional<ElfMemoryRegion> debug_info;
    std::optional<ElfMemoryRegion> binary;

    if (!entry.debug_info.empty()) {
      debug_info = ElfMemoryRegion(base, entry.debug_info);
    }

    if (!entry.binary.empty()) {
      binary = ElfMemoryRegion(base, entry.binary);
    }

    debug_modules_.emplace(base,
                           Entry{.binary = std::move(binary), .debug_info = std::move(debug_info)});

    if (entry.binary.empty()) {
      continue;
    }

    auto elf = elflib::ElfLib::Create(entry.binary);
    if (!elf) {
      continue;
    }
    auto module = std::make_shared<FileMemoryRegion>(base, entry.binary);
    for (const auto& segment : elf->GetSegmentHeaders()) {
      // Only PT_LOAD segments are actually mapped. The rest are informational.
      if (segment.p_type != elflib::PT_LOAD) {
        continue;
      }
      if (segment.p_flags & elflib::PF_W) {
        // Writable segment. Data in the ELF file might not match what was present at the time of
        // the crash.
        continue;
      }
      regions_.emplace_back(base + segment.p_vaddr, base + segment.p_vaddr + segment.p_memsz,
                            module);
    }
  }
  std::sort(regions_.begin(), regions_.end());

  // Sanity check.
  uint64_t last_end = 0;
  for (auto& [start, end, mem] : regions_) {
    FX_CHECK(start >= last_end);
    last_end = end;
  }
}

std::vector<debug_ipc::MemoryBlock> MinidumpMemory::ReadMemoryBlocks(uint64_t address,
                                                                     uint64_t size) {
  uint64_t end = address + size;
  std::vector<debug_ipc::MemoryBlock> res;
  if (address == end) {
    return res;
  }
  for (auto& [region_start, region_end, region_memory] : regions_) {
    // Space before the first region and between any two regions.
    if (address < region_start) {
      auto& block = res.emplace_back();
      block.address = address;
      block.size = std::min(end, region_start) - address;
      block.valid = false;
      if (end <= region_start) {
        address = end;
        break;
      }
      address = region_start;
    }
    // Now we have address >= region_start.
    if (address < region_end) {
      auto& block = res.emplace_back();
      block.address = address;
      block.size = std::min(end, region_end) - address;
      block.data.resize(block.size);
      block.valid = region_memory->ReadBytes(address, block.size, block.data.data()).ok();
      if (!block.valid) {
        block.data.clear();
      }
      if (end <= region_end) {
        address = end;
        break;
      }
      address = region_end;
    }
  }
  // Space after the last region.
  if (address < end) {
    auto& block = res.emplace_back();
    block.address = address;
    block.size = end - address;
    block.valid = false;
  }
  return res;
}

unwinder::Memory* MinidumpMemory::GetMemoryRegion(uint64_t address) {
  for (auto& [start, end, memory] : regions_) {
    if (address >= start && address < end) {
      return memory.get();
    }
  }
  return nullptr;
}

std::vector<unwinder::Module> MinidumpMemory::GetUnwinderModules() {
  std::vector<unwinder::Module> res;
  res.reserve(debug_modules_.size());
  for (auto& [addr, entry] : debug_modules_) {
    unwinder::Memory* binary_memory = nullptr;
    unwinder::Memory* debug_info_memory = nullptr;

    if (entry.binary) {
      binary_memory = &entry.binary.value();
    }

    if (entry.debug_info) {
      debug_info_memory = &entry.debug_info.value();
    }

    res.emplace_back(addr, binary_memory, debug_info_memory, unwinder::Module::AddressMode::kFile);
  }
  return res;
}

unwinder::Error MinidumpMemory::SnapshotMemoryRegion::ReadBytes(uint64_t addr, uint64_t size,
                                                                void* dst) {
  if (addr < snapshot_->Address() || addr + size > snapshot_->Address() + snapshot_->Size()) {
    return unwinder::Error("out of boundary");
  }
  uint64_t offset = addr - snapshot_->Address();
  bool ok = ReadMinidumpMemorySnapshot(*snapshot_, [&](void* data, uint64_t actual_size) {
    if (offset + size > actual_size) {
      return false;
    }
    memcpy(dst, reinterpret_cast<uint8_t*>(data) + offset, size);
    return true;
  });
  if (ok) {
    return unwinder::Success();
  }
  return unwinder::Error("error reading from the memory snapshot");
}

std::string MinidumpGetBuildId(const crashpad::ModuleSnapshot& mod) {
  auto build_id = mod.BuildID();

  if (build_id.empty()) {
    return "";
  }

  // 2 hex characters per 1 byte, so the string size is twice the data size.
  std::string ret;
  ret.reserve(2 * build_id.size());
  for (const auto& byte : build_id) {
    ret.append(fxl::StringPrintf("%02hhx", byte));
  }

  return ret;
}

}  // namespace zxdb
