//===-- MinidumpFileBuilder.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "MinidumpFileBuilder.h"

#include "Plugins/Process/minidump/RegisterContextMinidump_ARM64.h"
#include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/RegisterValue.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Minidump.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/TargetParser/Triple.h"

#include "Plugins/Process/minidump/MinidumpTypes.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"

#include <algorithm>
#include <cinttypes>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <set>
#include <utility>
#include <vector>

using namespace lldb;
using namespace lldb_private;
using namespace llvm::minidump;

Status MinidumpFileBuilder::AddHeaderAndCalculateDirectories() {
  // First set the offset on the file, and on the bytes saved
  m_saved_data_size = HEADER_SIZE;
  // We know we will have at least Misc, SystemInfo, Modules, and ThreadList
  // (corresponding memory list for stacks), an additional memory list for
  // non-stacks, and a stream to mark this minidump was generated by LLDB.
  lldb_private::Target &target = m_process_sp->GetTarget();
  m_expected_directories = 6;
  // Check if OS is linux and reserve directory space for all linux specific
  // breakpad extension directories.
  if (target.GetArchitecture().GetTriple().getOS() ==
      llvm::Triple::OSType::Linux)
    m_expected_directories += 9;

  // Go through all of the threads and check for exceptions.
  std::vector<lldb::ThreadSP> threads =
      m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
  for (const ThreadSP &thread_sp : threads) {
    StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
    if (stop_info_sp) {
      const StopReason &stop_reason = stop_info_sp->GetStopReason();
      if (stop_reason != lldb::eStopReasonInvalid)
        m_expected_directories++;
    }
  }

  m_saved_data_size +=
      m_expected_directories * sizeof(llvm::minidump::Directory);
  Status error;
  offset_t new_offset = m_core_file->SeekFromStart(m_saved_data_size);
  if (new_offset != m_saved_data_size)
    error = Status::FromErrorStringWithFormat(
        "Failed to fill in header and directory "
        "sections. Written / Expected (%" PRIx64 " / %" PRIx64 ")",
        new_offset, m_saved_data_size);

  if (error.Fail())
    return error;

  return AddLLDBGeneratedStream();
}

Status MinidumpFileBuilder::AddDirectory(StreamType type,
                                         uint64_t stream_size) {
  // We explicitly cast type, an 32b enum, to uint32_t to avoid warnings.
  Status error;
  if (GetCurrentDataEndOffset() > UINT32_MAX) {
    error = Status::FromErrorStringWithFormat(
        "Unable to add directory for stream type "
        "%x, offset is greater then 32 bit limit.",
        (uint32_t)type);
    return error;
  }

  if (m_directories.size() + 1 > m_expected_directories) {
    error = Status::FromErrorStringWithFormat(
        "Unable to add directory for stream type %x, exceeded expected number "
        "of directories %zu.",
        (uint32_t)type, m_expected_directories);
    return error;
  }

  LocationDescriptor loc;
  loc.DataSize = static_cast<llvm::support::ulittle32_t>(stream_size);
  // Stream will begin at the current end of data section
  loc.RVA = static_cast<llvm::support::ulittle32_t>(GetCurrentDataEndOffset());

  Directory dir;
  dir.Type = static_cast<llvm::support::little_t<StreamType>>(type);
  dir.Location = loc;

  m_directories.push_back(dir);
  return error;
}

Status MinidumpFileBuilder::AddLLDBGeneratedStream() {
  Status error;
  StreamType type = StreamType::LLDBGenerated;
  return AddDirectory(type, 0);
}

Status MinidumpFileBuilder::AddSystemInfo() {
  Status error;
  const llvm::Triple &target_triple =
      m_process_sp->GetTarget().GetArchitecture().GetTriple();
  error =
      AddDirectory(StreamType::SystemInfo, sizeof(llvm::minidump::SystemInfo));
  if (error.Fail())
    return error;

  llvm::minidump::ProcessorArchitecture arch;
  switch (target_triple.getArch()) {
  case llvm::Triple::ArchType::x86_64:
    arch = ProcessorArchitecture::AMD64;
    break;
  case llvm::Triple::ArchType::x86:
    arch = ProcessorArchitecture::X86;
    break;
  case llvm::Triple::ArchType::arm:
    arch = ProcessorArchitecture::ARM;
    break;
  case llvm::Triple::ArchType::aarch64:
    arch = ProcessorArchitecture::ARM64;
    break;
  case llvm::Triple::ArchType::mips64:
  case llvm::Triple::ArchType::mips64el:
  case llvm::Triple::ArchType::mips:
  case llvm::Triple::ArchType::mipsel:
    arch = ProcessorArchitecture::MIPS;
    break;
  case llvm::Triple::ArchType::ppc64:
  case llvm::Triple::ArchType::ppc:
  case llvm::Triple::ArchType::ppc64le:
    arch = ProcessorArchitecture::PPC;
    break;
  default:
    error = Status::FromErrorStringWithFormat(
        "Architecture %s not supported.",
        target_triple.getArchName().str().c_str());
    return error;
  };

  llvm::support::little_t<OSPlatform> platform_id;
  switch (target_triple.getOS()) {
  case llvm::Triple::OSType::Linux:
    if (target_triple.getEnvironment() ==
        llvm::Triple::EnvironmentType::Android)
      platform_id = OSPlatform::Android;
    else
      platform_id = OSPlatform::Linux;
    break;
  case llvm::Triple::OSType::Win32:
    platform_id = OSPlatform::Win32NT;
    break;
  case llvm::Triple::OSType::MacOSX:
    platform_id = OSPlatform::MacOSX;
    break;
  case llvm::Triple::OSType::IOS:
    platform_id = OSPlatform::IOS;
    break;
  default:
    error = Status::FromErrorStringWithFormat(
        "OS %s not supported.", target_triple.getOSName().str().c_str());
    return error;
  };

  llvm::minidump::SystemInfo sys_info;
  sys_info.ProcessorArch =
      static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
  // Global offset to beginning of a csd_string in a data section
  sys_info.CSDVersionRVA = static_cast<llvm::support::ulittle32_t>(
      GetCurrentDataEndOffset() + sizeof(llvm::minidump::SystemInfo));
  sys_info.PlatformId = platform_id;
  m_data.AppendData(&sys_info, sizeof(llvm::minidump::SystemInfo));

  std::string csd_string;

  error = WriteString(csd_string, &m_data);
  if (error.Fail()) {
    error =
        Status::FromErrorString("Unable to convert the csd string to UTF16.");
    return error;
  }

  return error;
}

Status WriteString(const std::string &to_write,
                   lldb_private::DataBufferHeap *buffer) {
  Status error;
  // let the StringRef eat also null termination char
  llvm::StringRef to_write_ref(to_write.c_str(), to_write.size() + 1);
  llvm::SmallVector<llvm::UTF16, 128> to_write_utf16;

  bool converted = convertUTF8ToUTF16String(to_write_ref, to_write_utf16);
  if (!converted) {
    error = Status::FromErrorStringWithFormat(
        "Unable to convert the string to UTF16. Failed to convert %s",
        to_write.c_str());
    return error;
  }

  // size of the UTF16 string should be written without the null termination
  // character that is stored in 2 bytes
  llvm::support::ulittle32_t to_write_size(to_write_utf16.size_in_bytes() - 2);

  buffer->AppendData(&to_write_size, sizeof(llvm::support::ulittle32_t));
  buffer->AppendData(to_write_utf16.data(), to_write_utf16.size_in_bytes());

  return error;
}

llvm::Expected<uint64_t> getModuleFileSize(Target &target,
                                           const ModuleSP &mod) {
  // JIT module has the same vm and file size.
  uint64_t SizeOfImage = 0;
  if (mod->GetObjectFile()->CalculateType() == ObjectFile::Type::eTypeJIT) {
    for (const auto &section : *mod->GetObjectFile()->GetSectionList()) {
      SizeOfImage += section->GetByteSize();
    }
    return SizeOfImage;
  }
  SectionSP sect_sp = mod->GetObjectFile()->GetBaseAddress().GetSection();

  if (!sect_sp) {
    return llvm::createStringError(std::errc::operation_not_supported,
                                   "Couldn't obtain the section information.");
  }
  lldb::addr_t sect_addr = sect_sp->GetLoadBaseAddress(&target);
  // Use memory size since zero fill sections, like ".bss", will be smaller on
  // disk.
  lldb::addr_t sect_size = sect_sp->GetByteSize();
  // This will usually be zero, but make sure to calculate the BaseOfImage
  // offset.
  const lldb::addr_t base_sect_offset =
      mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target) -
      sect_addr;
  SizeOfImage = sect_size - base_sect_offset;
  lldb::addr_t next_sect_addr = sect_addr + sect_size;
  Address sect_so_addr;
  target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
  lldb::SectionSP next_sect_sp = sect_so_addr.GetSection();
  while (next_sect_sp &&
         next_sect_sp->GetLoadBaseAddress(&target) == next_sect_addr) {
    sect_size = sect_sp->GetByteSize();
    SizeOfImage += sect_size;
    next_sect_addr += sect_size;
    target.ResolveLoadAddress(next_sect_addr, sect_so_addr);
    next_sect_sp = sect_so_addr.GetSection();
  }

  return SizeOfImage;
}

// ModuleList stream consists of a number of modules, followed by an array
// of llvm::minidump::Module's structures. Every structure informs about a
// single module. Additional data of variable length, such as module's names,
// are stored just after the ModuleList stream. The llvm::minidump::Module
// structures point to this helper data by global offset.
Status MinidumpFileBuilder::AddModuleList() {
  constexpr size_t minidump_module_size = sizeof(llvm::minidump::Module);
  Status error;

  lldb_private::Target &target = m_process_sp->GetTarget();
  const ModuleList &modules = target.GetImages();
  llvm::support::ulittle32_t modules_count =
      static_cast<llvm::support::ulittle32_t>(modules.GetSize());

  // This helps us with getting the correct global offset in minidump
  // file later, when we will be setting up offsets from the
  // the llvm::minidump::Module's structures into helper data
  size_t size_before = GetCurrentDataEndOffset();

  // This is the size of the main part of the ModuleList stream.
  // It consists of a module number and corresponding number of
  // structs describing individual modules
  size_t module_stream_size =
      sizeof(llvm::support::ulittle32_t) + modules_count * minidump_module_size;

  // Adding directory describing this stream.
  error = AddDirectory(StreamType::ModuleList, module_stream_size);
  if (error.Fail())
    return error;

  m_data.AppendData(&modules_count, sizeof(llvm::support::ulittle32_t));

  // Temporary storage for the helper data (of variable length)
  // as these cannot be dumped to m_data before dumping entire
  // array of module structures.
  DataBufferHeap helper_data;

  for (size_t i = 0; i < modules_count; ++i) {
    ModuleSP mod = modules.GetModuleAtIndex(i);
    std::string module_name = mod->GetSpecificationDescription();
    auto maybe_mod_size = getModuleFileSize(target, mod);
    if (!maybe_mod_size) {
      llvm::Error mod_size_err = maybe_mod_size.takeError();
      llvm::handleAllErrors(std::move(mod_size_err),
                            [&](const llvm::ErrorInfoBase &E) {
                              error = Status::FromErrorStringWithFormat(
                                  "Unable to get the size of module %s: %s.",
                                  module_name.c_str(), E.message().c_str());
                            });
      return error;
    }

    uint64_t mod_size = std::move(*maybe_mod_size);

    llvm::support::ulittle32_t signature =
        static_cast<llvm::support::ulittle32_t>(
            static_cast<uint32_t>(minidump::CvSignature::ElfBuildId));
    auto uuid = mod->GetUUID().GetBytes();

    VSFixedFileInfo info;
    info.Signature = static_cast<llvm::support::ulittle32_t>(0u);
    info.StructVersion = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
    info.ProductVersionHigh = static_cast<llvm::support::ulittle32_t>(0u);
    info.ProductVersionLow = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileFlagsMask = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileFlags = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileOS = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileType = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileSubtype = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileDateHigh = static_cast<llvm::support::ulittle32_t>(0u);
    info.FileDateLow = static_cast<llvm::support::ulittle32_t>(0u);

    LocationDescriptor ld;
    ld.DataSize = static_cast<llvm::support::ulittle32_t>(0u);
    ld.RVA = static_cast<llvm::support::ulittle32_t>(0u);

    // Setting up LocationDescriptor for uuid string. The global offset into
    // minidump file is calculated.
    LocationDescriptor ld_cv;
    ld_cv.DataSize = static_cast<llvm::support::ulittle32_t>(
        sizeof(llvm::support::ulittle32_t) + uuid.size());
    ld_cv.RVA = static_cast<llvm::support::ulittle32_t>(
        size_before + module_stream_size + helper_data.GetByteSize());

    helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
    helper_data.AppendData(uuid.begin(), uuid.size());

    llvm::minidump::Module m;
    m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
        mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
    m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size);
    m.Checksum = static_cast<llvm::support::ulittle32_t>(0);
    m.TimeDateStamp =
        static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
    m.ModuleNameRVA = static_cast<llvm::support::ulittle32_t>(
        size_before + module_stream_size + helper_data.GetByteSize());
    m.VersionInfo = info;
    m.CvRecord = ld_cv;
    m.MiscRecord = ld;

    error = WriteString(module_name, &helper_data);

    if (error.Fail())
      return error;

    m_data.AppendData(&m, sizeof(llvm::minidump::Module));
  }

  m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
  return error;
}

uint16_t read_register_u16_raw(RegisterContext *reg_ctx,
                               llvm::StringRef reg_name) {
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
  if (!reg_info)
    return 0;
  lldb_private::RegisterValue reg_value;
  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
  if (!success)
    return 0;
  return reg_value.GetAsUInt16();
}

uint32_t read_register_u32_raw(RegisterContext *reg_ctx,
                               llvm::StringRef reg_name) {
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
  if (!reg_info)
    return 0;
  lldb_private::RegisterValue reg_value;
  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
  if (!success)
    return 0;
  return reg_value.GetAsUInt32();
}

uint64_t read_register_u64_raw(RegisterContext *reg_ctx,
                               llvm::StringRef reg_name) {
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
  if (!reg_info)
    return 0;
  lldb_private::RegisterValue reg_value;
  bool success = reg_ctx->ReadRegister(reg_info, reg_value);
  if (!success)
    return 0;
  return reg_value.GetAsUInt64();
}

llvm::support::ulittle16_t read_register_u16(RegisterContext *reg_ctx,
                                             llvm::StringRef reg_name) {
  return static_cast<llvm::support::ulittle16_t>(
      read_register_u16_raw(reg_ctx, reg_name));
}

llvm::support::ulittle32_t read_register_u32(RegisterContext *reg_ctx,
                                             llvm::StringRef reg_name) {
  return static_cast<llvm::support::ulittle32_t>(
      read_register_u32_raw(reg_ctx, reg_name));
}

llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx,
                                             llvm::StringRef reg_name) {
  return static_cast<llvm::support::ulittle64_t>(
      read_register_u64_raw(reg_ctx, reg_name));
}

void read_register_u128(RegisterContext *reg_ctx, llvm::StringRef reg_name,
                        uint8_t *dst) {
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
  if (reg_info) {
    lldb_private::RegisterValue reg_value;
    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
      Status error;
      uint32_t bytes_copied = reg_value.GetAsMemoryData(
          *reg_info, dst, 16, lldb::ByteOrder::eByteOrderLittle, error);
      if (bytes_copied == 16)
        return;
    }
  }
  // If anything goes wrong, then zero out the register value.
  memset(dst, 0, 16);
}

lldb_private::minidump::MinidumpContext_x86_64
GetThreadContext_x86_64(RegisterContext *reg_ctx) {
  lldb_private::minidump::MinidumpContext_x86_64 thread_context = {};
  thread_context.p1_home = {};
  thread_context.context_flags = static_cast<uint32_t>(
      lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag |
      lldb_private::minidump::MinidumpContext_x86_64_Flags::Control |
      lldb_private::minidump::MinidumpContext_x86_64_Flags::Segments |
      lldb_private::minidump::MinidumpContext_x86_64_Flags::Integer |
      lldb_private::minidump::MinidumpContext_x86_64_Flags::LLDBSpecific);
  thread_context.rax = read_register_u64(reg_ctx, "rax");
  thread_context.rbx = read_register_u64(reg_ctx, "rbx");
  thread_context.rcx = read_register_u64(reg_ctx, "rcx");
  thread_context.rdx = read_register_u64(reg_ctx, "rdx");
  thread_context.rdi = read_register_u64(reg_ctx, "rdi");
  thread_context.rsi = read_register_u64(reg_ctx, "rsi");
  thread_context.rbp = read_register_u64(reg_ctx, "rbp");
  thread_context.rsp = read_register_u64(reg_ctx, "rsp");
  thread_context.r8 = read_register_u64(reg_ctx, "r8");
  thread_context.r9 = read_register_u64(reg_ctx, "r9");
  thread_context.r10 = read_register_u64(reg_ctx, "r10");
  thread_context.r11 = read_register_u64(reg_ctx, "r11");
  thread_context.r12 = read_register_u64(reg_ctx, "r12");
  thread_context.r13 = read_register_u64(reg_ctx, "r13");
  thread_context.r14 = read_register_u64(reg_ctx, "r14");
  thread_context.r15 = read_register_u64(reg_ctx, "r15");
  thread_context.rip = read_register_u64(reg_ctx, "rip");
  // To make our code agnostic to whatever type the register value identifies
  // itself as, we read as a u64 and truncate to u32/u16 ourselves.
  thread_context.eflags = read_register_u64(reg_ctx, "rflags");
  thread_context.cs = read_register_u64(reg_ctx, "cs");
  thread_context.fs = read_register_u64(reg_ctx, "fs");
  thread_context.gs = read_register_u64(reg_ctx, "gs");
  thread_context.ss = read_register_u64(reg_ctx, "ss");
  thread_context.ds = read_register_u64(reg_ctx, "ds");
  thread_context.fs_base = read_register_u64(reg_ctx, "fs_base");
  thread_context.gs_base = read_register_u64(reg_ctx, "gs_base");
  return thread_context;
}

minidump::RegisterContextMinidump_ARM64::Context
GetThreadContext_ARM64(RegisterContext *reg_ctx) {
  minidump::RegisterContextMinidump_ARM64::Context thread_context = {};
  thread_context.context_flags = static_cast<uint32_t>(
      minidump::RegisterContextMinidump_ARM64::Flags::ARM64_Flag |
      minidump::RegisterContextMinidump_ARM64::Flags::Integer |
      minidump::RegisterContextMinidump_ARM64::Flags::FloatingPoint);
  char reg_name[16];
  for (uint32_t i = 0; i < 31; ++i) {
    snprintf(reg_name, sizeof(reg_name), "x%u", i);
    thread_context.x[i] = read_register_u64(reg_ctx, reg_name);
  }
  // Work around a bug in debugserver where "sp" on arm64 doesn't have the alt
  // name set to "x31"
  thread_context.x[31] = read_register_u64(reg_ctx, "sp");
  thread_context.pc = read_register_u64(reg_ctx, "pc");
  thread_context.cpsr = read_register_u32(reg_ctx, "cpsr");
  thread_context.fpsr = read_register_u32(reg_ctx, "fpsr");
  thread_context.fpcr = read_register_u32(reg_ctx, "fpcr");
  for (uint32_t i = 0; i < 32; ++i) {
    snprintf(reg_name, sizeof(reg_name), "v%u", i);
    read_register_u128(reg_ctx, reg_name, &thread_context.v[i * 16]);
  }
  return thread_context;
}

class ArchThreadContexts {
  llvm::Triple::ArchType m_arch;
  union {
    lldb_private::minidump::MinidumpContext_x86_64 x86_64;
    lldb_private::minidump::RegisterContextMinidump_ARM64::Context arm64;
  };

public:
  ArchThreadContexts(llvm::Triple::ArchType arch) : m_arch(arch) {}

  bool prepareRegisterContext(RegisterContext *reg_ctx) {
    switch (m_arch) {
    case llvm::Triple::ArchType::x86_64:
      x86_64 = GetThreadContext_x86_64(reg_ctx);
      return true;
    case llvm::Triple::ArchType::aarch64:
      arm64 = GetThreadContext_ARM64(reg_ctx);
      return true;
    default:
      break;
    }
    return false;
  }

  const void *data() const { return &x86_64; }

  size_t size() const {
    switch (m_arch) {
    case llvm::Triple::ArchType::x86_64:
      return sizeof(x86_64);
    case llvm::Triple::ArchType::aarch64:
      return sizeof(arm64);
    default:
      break;
    }
    return 0;
  }
};

Status MinidumpFileBuilder::FixThreadStacks() {
  Status error;
  // If we have anything in the heap flush it.
  FlushBufferToDisk();
  m_core_file->SeekFromStart(m_thread_list_start);
  for (auto &pair : m_thread_by_range_end) {
    // The thread objects will get a new memory descriptor added
    // When we are emitting the memory list and then we write it here
    const llvm::minidump::Thread &thread = pair.second;
    size_t bytes_to_write = sizeof(llvm::minidump::Thread);
    size_t bytes_written = bytes_to_write;
    error = m_core_file->Write(&thread, bytes_written);
    if (error.Fail() || bytes_to_write != bytes_written) {
      error = Status::FromErrorStringWithFormat(
          "Wrote incorrect number of bytes to minidump file. (written %zd/%zd)",
          bytes_written, bytes_to_write);
      return error;
    }
  }

  return error;
}

Status MinidumpFileBuilder::AddThreadList() {
  constexpr size_t minidump_thread_size = sizeof(llvm::minidump::Thread);
  std::vector<ThreadSP> thread_list =
      m_process_sp->CalculateCoreFileThreadList(m_save_core_options);

  // size of the entire thread stream consists of:
  // number of threads and threads array
  size_t thread_stream_size = sizeof(llvm::support::ulittle32_t) +
                              thread_list.size() * minidump_thread_size;
  // save for the ability to set up RVA
  size_t size_before = GetCurrentDataEndOffset();
  Status error;
  error = AddDirectory(StreamType::ThreadList, thread_stream_size);
  if (error.Fail())
    return error;

  llvm::support::ulittle32_t thread_count =
      static_cast<llvm::support::ulittle32_t>(thread_list.size());
  m_data.AppendData(&thread_count, sizeof(llvm::support::ulittle32_t));

  // Take the offset after the thread count.
  m_thread_list_start = GetCurrentDataEndOffset();
  DataBufferHeap helper_data;

  Log *log = GetLog(LLDBLog::Object);
  for (const ThreadSP &thread_sp : thread_list) {
    RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());

    if (!reg_ctx_sp) {
      error = Status::FromErrorString("Unable to get the register context.");
      return error;
    }
    RegisterContext *reg_ctx = reg_ctx_sp.get();
    Target &target = m_process_sp->GetTarget();
    const ArchSpec &arch = target.GetArchitecture();
    ArchThreadContexts thread_context(arch.GetMachine());
    if (!thread_context.prepareRegisterContext(reg_ctx)) {
      error = Status::FromErrorStringWithFormat(
          "architecture %s not supported.",
          arch.GetTriple().getArchName().str().c_str());
      return error;
    }

    uint64_t sp = reg_ctx->GetSP();
    MemoryRegionInfo sp_region;
    m_process_sp->GetMemoryRegionInfo(sp, sp_region);

    // Emit a blank descriptor
    MemoryDescriptor stack;
    LocationDescriptor empty_label;
    empty_label.DataSize = 0;
    empty_label.RVA = 0;
    stack.Memory = empty_label;
    stack.StartOfMemoryRange = 0;
    LocationDescriptor thread_context_memory_locator;
    thread_context_memory_locator.DataSize =
        static_cast<llvm::support::ulittle32_t>(thread_context.size());
    thread_context_memory_locator.RVA = static_cast<llvm::support::ulittle32_t>(
        size_before + thread_stream_size + helper_data.GetByteSize());
    // Cache thie thread context memory so we can reuse for exceptions.
    m_tid_to_reg_ctx[thread_sp->GetID()] = thread_context_memory_locator;

    LLDB_LOGF(log, "AddThreadList for thread %d: thread_context %zu bytes",
              thread_sp->GetIndexID(), thread_context.size());
    helper_data.AppendData(thread_context.data(), thread_context.size());

    llvm::minidump::Thread t;
    t.ThreadId = static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
    t.SuspendCount = static_cast<llvm::support::ulittle32_t>(
        (thread_sp->GetState() == StateType::eStateSuspended) ? 1 : 0);
    t.PriorityClass = static_cast<llvm::support::ulittle32_t>(0);
    t.Priority = static_cast<llvm::support::ulittle32_t>(0);
    t.EnvironmentBlock = static_cast<llvm::support::ulittle64_t>(0);
    t.Stack = stack, t.Context = thread_context_memory_locator;

    // We save off the stack object so we can circle back and clean it up.
    m_thread_by_range_end[sp_region.GetRange().GetRangeEnd()] = t;
    m_data.AppendData(&t, sizeof(llvm::minidump::Thread));
  }

  LLDB_LOGF(log, "AddThreadList(): total helper_data %" PRIx64 " bytes",
            helper_data.GetByteSize());
  m_data.AppendData(helper_data.GetBytes(), helper_data.GetByteSize());
  return Status();
}

Status MinidumpFileBuilder::AddExceptions() {
  std::vector<ThreadSP> thread_list =
      m_process_sp->CalculateCoreFileThreadList(m_save_core_options);
  Status error;
  for (const ThreadSP &thread_sp : thread_list) {
    StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
    // If we don't have a stop info, or if it's invalid, skip.
    if (!stop_info_sp ||
        stop_info_sp->GetStopReason() == lldb::eStopReasonInvalid)
      continue;

    constexpr size_t minidump_exception_size =
        sizeof(llvm::minidump::ExceptionStream);
    error = AddDirectory(StreamType::Exception, minidump_exception_size);
    if (error.Fail())
      return error;

    RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
    Exception exp_record = {};
    exp_record.ExceptionCode =
        static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
    exp_record.ExceptionFlags =
        static_cast<llvm::support::ulittle32_t>(Exception::LLDB_FLAG);
    exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
    exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
    exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(1);
    std::string description = stop_info_sp->GetDescription();
    // We have 120 bytes to work with and it's unlikely description will
    // overflow, but we gotta check.
    memcpy(&exp_record.ExceptionInformation, description.c_str(),
           std::max(description.size(), Exception::MaxParameterBytes));
    exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
    ExceptionStream exp_stream;
    exp_stream.ThreadId =
        static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
    exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
    exp_stream.ExceptionRecord = exp_record;
    auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
    if (Iter != m_tid_to_reg_ctx.end()) {
      exp_stream.ThreadContext = Iter->second;
    } else {
      exp_stream.ThreadContext.DataSize = 0;
      exp_stream.ThreadContext.RVA = 0;
    }
    m_data.AppendData(&exp_stream, minidump_exception_size);
  }

  return error;
}

lldb_private::Status MinidumpFileBuilder::AddMiscInfo() {
  Status error;
  error = AddDirectory(StreamType::MiscInfo,
                       sizeof(lldb_private::minidump::MinidumpMiscInfo));
  if (error.Fail())
    return error;

  lldb_private::minidump::MinidumpMiscInfo misc_info;
  misc_info.size = static_cast<llvm::support::ulittle32_t>(
      sizeof(lldb_private::minidump::MinidumpMiscInfo));
  // Default set flags1 to 0, in case that we will not be able to
  // get any information
  misc_info.flags1 = static_cast<llvm::support::ulittle32_t>(0);

  lldb_private::ProcessInstanceInfo process_info;
  m_process_sp->GetProcessInfo(process_info);
  if (process_info.ProcessIDIsValid()) {
    // Set flags1 to reflect that PID is filled in
    misc_info.flags1 =
        static_cast<llvm::support::ulittle32_t>(static_cast<uint32_t>(
            lldb_private::minidump::MinidumpMiscInfoFlags::ProcessID));
    misc_info.process_id =
        static_cast<llvm::support::ulittle32_t>(process_info.GetProcessID());
  }

  m_data.AppendData(&misc_info,
                    sizeof(lldb_private::minidump::MinidumpMiscInfo));
  return error;
}

std::unique_ptr<llvm::MemoryBuffer>
getFileStreamHelper(const std::string &path) {
  auto maybe_stream = llvm::MemoryBuffer::getFileAsStream(path);
  if (!maybe_stream)
    return nullptr;
  return std::move(maybe_stream.get());
}

Status MinidumpFileBuilder::AddLinuxFileStreams() {
  Status error;
  // No-op if we are not on linux.
  if (m_process_sp->GetTarget().GetArchitecture().GetTriple().getOS() !=
      llvm::Triple::Linux)
    return error;

  std::vector<std::pair<StreamType, std::string>> files_with_stream_types = {
      {StreamType::LinuxCPUInfo, "/proc/cpuinfo"},
      {StreamType::LinuxLSBRelease, "/etc/lsb-release"},
  };

  lldb_private::ProcessInstanceInfo process_info;
  m_process_sp->GetProcessInfo(process_info);
  if (process_info.ProcessIDIsValid()) {
    lldb::pid_t pid = process_info.GetProcessID();
    std::string pid_str = std::to_string(pid);
    files_with_stream_types.push_back(
        {StreamType::LinuxProcStatus, "/proc/" + pid_str + "/status"});
    files_with_stream_types.push_back(
        {StreamType::LinuxCMDLine, "/proc/" + pid_str + "/cmdline"});
    files_with_stream_types.push_back(
        {StreamType::LinuxEnviron, "/proc/" + pid_str + "/environ"});
    files_with_stream_types.push_back(
        {StreamType::LinuxAuxv, "/proc/" + pid_str + "/auxv"});
    files_with_stream_types.push_back(
        {StreamType::LinuxMaps, "/proc/" + pid_str + "/maps"});
    files_with_stream_types.push_back(
        {StreamType::LinuxProcStat, "/proc/" + pid_str + "/stat"});
    files_with_stream_types.push_back(
        {StreamType::LinuxProcFD, "/proc/" + pid_str + "/fd"});
  }

  for (const auto &entry : files_with_stream_types) {
    StreamType stream = entry.first;
    std::string path = entry.second;
    auto memory_buffer = getFileStreamHelper(path);

    if (memory_buffer) {
      size_t size = memory_buffer->getBufferSize();
      if (size == 0)
        continue;
      error = AddDirectory(stream, size);
      if (error.Fail())
        return error;
      m_data.AppendData(memory_buffer->getBufferStart(), size);
    }
  }

  return error;
}

Status MinidumpFileBuilder::AddMemoryList() {
  Status error;

  // We first save the thread stacks to ensure they fit in the first UINT32_MAX
  // bytes of the core file. Thread structures in minidump files can only use
  // 32 bit memory descriptiors, so we emit them first to ensure the memory is
  // in accessible with a 32 bit offset.
  std::vector<CoreFileMemoryRange> ranges_32;
  std::vector<CoreFileMemoryRange> ranges_64;
  CoreFileMemoryRanges all_core_memory_ranges;
  error = m_process_sp->CalculateCoreFileSaveRanges(m_save_core_options,
                                                    all_core_memory_ranges);

  if (error.Fail())
    return error;

  lldb_private::Progress progress("Saving Minidump File", "",
                                  all_core_memory_ranges.GetSize());
  std::vector<CoreFileMemoryRange> all_core_memory_vec;
  // Extract all the data into just a vector of data. So we can mutate this in
  // place.
  for (const auto &core_range : all_core_memory_ranges)
    all_core_memory_vec.push_back(core_range.data);

  // Start by saving all of the stacks and ensuring they fit under the 32b
  // limit.
  uint64_t total_size = GetCurrentDataEndOffset();
  auto iterator = all_core_memory_vec.begin();
  while (iterator != all_core_memory_vec.end()) {
    if (m_thread_by_range_end.count(iterator->range.end()) > 0) {
      // We don't save stacks twice.
      ranges_32.push_back(*iterator);
      total_size +=
          iterator->range.size() + sizeof(llvm::minidump::MemoryDescriptor);
      iterator = all_core_memory_vec.erase(iterator);
    } else {
      iterator++;
    }
  }

  if (total_size >= UINT32_MAX) {
    error = Status::FromErrorStringWithFormat(
        "Unable to write minidump. Stack memory "
        "exceeds 32b limit. (Num Stacks %zu)",
        ranges_32.size());
    return error;
  }

  // After saving the stacks, we start packing as much as we can into 32b.
  // We apply a generous padding here so that the Directory, MemoryList and
  // Memory64List sections all begin in 32b addressable space.
  // Then anything overflow extends into 64b addressable space.
  // All core memeroy ranges will either container nothing on stacks only
  // or all the memory ranges including stacks
  if (!all_core_memory_vec.empty())
    total_size += 256 + (all_core_memory_vec.size() *
                         sizeof(llvm::minidump::MemoryDescriptor_64));

  for (const auto &core_range : all_core_memory_vec) {
    const addr_t range_size = core_range.range.size();
    // We don't need to check for stacks here because we already removed them
    // from all_core_memory_ranges.
    if (total_size + range_size < UINT32_MAX) {
      ranges_32.push_back(core_range);
      total_size += range_size;
    } else {
      ranges_64.push_back(core_range);
    }
  }

  error = AddMemoryList_32(ranges_32, progress);
  if (error.Fail())
    return error;

  // Add the remaining memory as a 64b range.
  if (!ranges_64.empty()) {
    error = AddMemoryList_64(ranges_64, progress);
    if (error.Fail())
      return error;
  }

  return FixThreadStacks();
}

Status MinidumpFileBuilder::DumpHeader() const {
  // write header
  llvm::minidump::Header header;
  header.Signature = static_cast<llvm::support::ulittle32_t>(
      llvm::minidump::Header::MagicSignature);
  header.Version = static_cast<llvm::support::ulittle32_t>(
      llvm::minidump::Header::MagicVersion);
  header.NumberOfStreams =
      static_cast<llvm::support::ulittle32_t>(m_directories.size());
  // We write the directories right after the header.
  header.StreamDirectoryRVA =
      static_cast<llvm::support::ulittle32_t>(HEADER_SIZE);
  header.Checksum = static_cast<llvm::support::ulittle32_t>(
      0u), // not used in most of the writers
      header.TimeDateStamp =
          static_cast<llvm::support::ulittle32_t>(std::time(nullptr));
  header.Flags =
      static_cast<llvm::support::ulittle64_t>(0u); // minidump normal flag

  Status error;
  size_t bytes_written;

  m_core_file->SeekFromStart(0);
  bytes_written = HEADER_SIZE;
  error = m_core_file->Write(&header, bytes_written);
  if (error.Fail() || bytes_written != HEADER_SIZE) {
    if (bytes_written != HEADER_SIZE)
      error = Status::FromErrorStringWithFormat(
          "Unable to write the minidump header (written %zd/%zd)",
          bytes_written, HEADER_SIZE);
    return error;
  }
  return error;
}

offset_t MinidumpFileBuilder::GetCurrentDataEndOffset() const {
  return m_data.GetByteSize() + m_saved_data_size;
}

Status MinidumpFileBuilder::DumpDirectories() const {
  Status error;
  size_t bytes_written;
  m_core_file->SeekFromStart(HEADER_SIZE);
  for (const Directory &dir : m_directories) {
    bytes_written = DIRECTORY_SIZE;
    error = m_core_file->Write(&dir, bytes_written);
    if (error.Fail() || bytes_written != DIRECTORY_SIZE) {
      if (bytes_written != DIRECTORY_SIZE)
        error = Status::FromErrorStringWithFormat(
            "unable to write the directory (written %zd/%zd)", bytes_written,
            DIRECTORY_SIZE);
      return error;
    }
  }

  return error;
}

static uint64_t
GetLargestRangeSize(const std::vector<CoreFileMemoryRange> &ranges) {
  uint64_t max_size = 0;
  for (const auto &core_range : ranges)
    max_size = std::max(max_size, core_range.range.size());
  return max_size;
}

Status
MinidumpFileBuilder::AddMemoryList_32(std::vector<CoreFileMemoryRange> &ranges,
                                      Progress &progress) {
  std::vector<MemoryDescriptor> descriptors;
  Status error;
  if (ranges.size() == 0)
    return error;

  Log *log = GetLog(LLDBLog::Object);
  size_t region_index = 0;
  auto data_up =
      std::make_unique<DataBufferHeap>(GetLargestRangeSize(ranges), 0);
  for (const auto &core_range : ranges) {
    // Take the offset before we write.
    const offset_t offset_for_data = GetCurrentDataEndOffset();
    const addr_t addr = core_range.range.start();
    const addr_t size = core_range.range.size();
    const addr_t end = core_range.range.end();

    LLDB_LOGF(log,
              "AddMemoryList %zu/%zu reading memory for region "
              "(%" PRIx64 " bytes) [%" PRIx64 ", %" PRIx64 ")",
              region_index, ranges.size(), size, addr, addr + size);
    ++region_index;

    progress.Increment(1, "Adding Memory Range " + core_range.Dump());
    const size_t bytes_read =
        m_process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
    if (error.Fail() || bytes_read == 0) {
      LLDB_LOGF(log, "Failed to read memory region. Bytes read: %zu, error: %s",
                bytes_read, error.AsCString());
      // Just skip sections with errors or zero bytes in 32b mode
      continue;
    } else if (bytes_read != size) {
      LLDB_LOGF(
          log, "Memory region at: %" PRIx64 " failed to read %" PRIx64 " bytes",
          addr, size);
    }

    MemoryDescriptor descriptor;
    descriptor.StartOfMemoryRange =
        static_cast<llvm::support::ulittle64_t>(addr);
    descriptor.Memory.DataSize =
        static_cast<llvm::support::ulittle32_t>(bytes_read);
    descriptor.Memory.RVA =
        static_cast<llvm::support::ulittle32_t>(offset_for_data);
    descriptors.push_back(descriptor);
    if (m_thread_by_range_end.count(end) > 0)
      m_thread_by_range_end[end].Stack = descriptor;

    // Add the data to the buffer, flush as needed.
    error = AddData(data_up->GetBytes(), bytes_read);
    if (error.Fail())
      return error;
  }

  // Add a directory that references this list
  // With a size of the number of ranges as a 32 bit num
  // And then the size of all the ranges
  error = AddDirectory(StreamType::MemoryList,
                       sizeof(llvm::minidump::MemoryListHeader) +
                           descriptors.size() *
                               sizeof(llvm::minidump::MemoryDescriptor));
  if (error.Fail())
    return error;

  llvm::minidump::MemoryListHeader list_header;
  llvm::support::ulittle32_t memory_ranges_num =
      static_cast<llvm::support::ulittle32_t>(descriptors.size());
  list_header.NumberOfMemoryRanges = memory_ranges_num;
  m_data.AppendData(&list_header, sizeof(llvm::minidump::MemoryListHeader));
  // For 32b we can get away with writing off the descriptors after the data.
  // This means no cleanup loop needed.
  m_data.AppendData(descriptors.data(),
                    descriptors.size() * sizeof(MemoryDescriptor));

  return error;
}

Status
MinidumpFileBuilder::AddMemoryList_64(std::vector<CoreFileMemoryRange> &ranges,
                                      Progress &progress) {
  Status error;
  if (ranges.empty())
    return error;

  error = AddDirectory(StreamType::Memory64List,
                       (sizeof(llvm::support::ulittle64_t) * 2) +
                           ranges.size() *
                               sizeof(llvm::minidump::MemoryDescriptor_64));
  if (error.Fail())
    return error;

  llvm::minidump::Memory64ListHeader list_header;
  llvm::support::ulittle64_t memory_ranges_num =
      static_cast<llvm::support::ulittle64_t>(ranges.size());
  list_header.NumberOfMemoryRanges = memory_ranges_num;
  // Capture the starting offset for all the descriptors so we can clean them up
  // if needed.
  offset_t starting_offset =
      GetCurrentDataEndOffset() + sizeof(llvm::support::ulittle64_t);
  // The base_rva needs to start after the directories, which is right after
  // this 8 byte variable.
  offset_t base_rva =
      starting_offset +
      (ranges.size() * sizeof(llvm::minidump::MemoryDescriptor_64));
  llvm::support::ulittle64_t memory_ranges_base_rva =
      static_cast<llvm::support::ulittle64_t>(base_rva);
  list_header.BaseRVA = memory_ranges_base_rva;
  m_data.AppendData(&list_header, sizeof(llvm::minidump::Memory64ListHeader));

  bool cleanup_required = false;
  std::vector<MemoryDescriptor_64> descriptors;
  // Enumerate the ranges and create the memory descriptors so we can append
  // them first
  for (const auto core_range : ranges) {
    // Add the space required to store the memory descriptor
    MemoryDescriptor_64 memory_desc;
    memory_desc.StartOfMemoryRange =
        static_cast<llvm::support::ulittle64_t>(core_range.range.start());
    memory_desc.DataSize =
        static_cast<llvm::support::ulittle64_t>(core_range.range.size());
    descriptors.push_back(memory_desc);
    // Now write this memory descriptor to the buffer.
    m_data.AppendData(&memory_desc, sizeof(MemoryDescriptor_64));
  }

  Log *log = GetLog(LLDBLog::Object);
  size_t region_index = 0;
  auto data_up =
      std::make_unique<DataBufferHeap>(GetLargestRangeSize(ranges), 0);
  for (const auto &core_range : ranges) {
    const addr_t addr = core_range.range.start();
    const addr_t size = core_range.range.size();

    LLDB_LOGF(log,
              "AddMemoryList_64 %zu/%zu reading memory for region "
              "(%" PRIx64 "bytes) "
              "[%" PRIx64 ", %" PRIx64 ")",
              region_index, ranges.size(), size, addr, addr + size);
    ++region_index;

    progress.Increment(1, "Adding Memory Range " + core_range.Dump());
    const size_t bytes_read =
        m_process_sp->ReadMemory(addr, data_up->GetBytes(), size, error);
    if (error.Fail()) {
      LLDB_LOGF(log, "Failed to read memory region. Bytes read: %zu, error: %s",
                bytes_read, error.AsCString());
      error.Clear();
      cleanup_required = true;
      descriptors[region_index].DataSize = 0;
    }
    if (bytes_read != size) {
      LLDB_LOGF(
          log, "Memory region at: %" PRIx64 " failed to read %" PRIx64 " bytes",
          addr, size);
      cleanup_required = true;
      descriptors[region_index].DataSize = bytes_read;
    }

    // Add the data to the buffer, flush as needed.
    error = AddData(data_up->GetBytes(), bytes_read);
    if (error.Fail())
      return error;
  }

  // Early return if there is no cleanup needed.
  if (!cleanup_required) {
    return error;
  } else {
    // Flush to disk we can make the fixes in place.
    FlushBufferToDisk();
    // Fixup the descriptors that were not read correctly.
    m_core_file->SeekFromStart(starting_offset);
    size_t bytes_written = sizeof(MemoryDescriptor_64) * descriptors.size();
    error = m_core_file->Write(descriptors.data(), bytes_written);
    if (error.Fail() ||
        bytes_written != sizeof(MemoryDescriptor_64) * descriptors.size()) {
      error = Status::FromErrorStringWithFormat(
          "unable to write the memory descriptors (written %zd/%zd)",
          bytes_written, sizeof(MemoryDescriptor_64) * descriptors.size());
    }

    return error;
  }
}

Status MinidumpFileBuilder::AddData(const void *data, uint64_t size) {
  // This should also get chunked, because worst case we copy over a big
  // object / memory range, say 5gb. In that case, we'd have to allocate 10gb
  // 5 gb for the buffer we're copying from, and then 5gb for the buffer we're
  // copying to. Which will be short lived and immedaitely go to disk, the goal
  // here is to limit the number of bytes we need to host in memory at any given
  // time.
  m_data.AppendData(data, size);
  if (m_data.GetByteSize() > MAX_WRITE_CHUNK_SIZE)
    return FlushBufferToDisk();

  return Status();
}

Status MinidumpFileBuilder::FlushBufferToDisk() {
  Status error;
  // Set the stream to it's end.
  m_core_file->SeekFromStart(m_saved_data_size);
  addr_t starting_size = m_data.GetByteSize();
  addr_t remaining_bytes = starting_size;
  offset_t offset = 0;

  while (remaining_bytes > 0) {
    size_t bytes_written = remaining_bytes;
    // We don't care how many bytes we wrote unless we got an error
    // so just decrement the remaining bytes.
    error = m_core_file->Write(m_data.GetBytes() + offset, bytes_written);
    if (error.Fail()) {
      error = Status::FromErrorStringWithFormat(
          "Wrote incorrect number of bytes to minidump file. (written %" PRIx64
          "/%" PRIx64 ")",
          starting_size - remaining_bytes, starting_size);
      return error;
    }

    offset += bytes_written;
    remaining_bytes -= bytes_written;
  }

  m_saved_data_size += starting_size;
  m_data.Clear();
  return error;
}

Status MinidumpFileBuilder::DumpFile() {
  Status error;
  // If anything is left unsaved, dump it.
  error = FlushBufferToDisk();
  if (error.Fail())
    return error;

  // Overwrite the header which we filled in earlier.
  error = DumpHeader();
  if (error.Fail())
    return error;

  // Overwrite the space saved for directories
  error = DumpDirectories();
  if (error.Fail())
    return error;

  return error;
}

void MinidumpFileBuilder::DeleteFile() noexcept {
  Log *log = GetLog(LLDBLog::Object);

  if (m_core_file) {
    Status error = m_core_file->Close();
    if (error.Fail())
      LLDB_LOGF(log, "Failed to close minidump file: %s", error.AsCString());

    m_core_file.reset();
  }
}
