//===-- ObjectFileMachO.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 "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"

#include <algorithm>

#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_riscv32.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"

#include "lldb/Host/SafeMachO.h"

#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"

#include "MachOTrie.h"
#include "ObjectFileMachO.h"

#if defined(__APPLE__)
#include <TargetConditionals.h>
// GetLLDBSharedCacheUUID() needs to call dlsym()
#include <dlfcn.h>
#include <mach/mach_init.h>
#include <mach/vm_map.h>
#include <lldb/Host/SafeMachO.h>
#endif

#ifndef __APPLE__
#include "lldb/Utility/AppleUuidCompatibility.h"
#else
#include <uuid/uuid.h>
#endif

#include <bitset>
#include <memory>
#include <optional>

// Unfortunately the signpost header pulls in the system MachO header, too.
#ifdef CPU_TYPE_ARM
#undef CPU_TYPE_ARM
#endif
#ifdef CPU_TYPE_ARM64
#undef CPU_TYPE_ARM64
#endif
#ifdef CPU_TYPE_ARM64_32
#undef CPU_TYPE_ARM64_32
#endif
#ifdef CPU_TYPE_X86_64
#undef CPU_TYPE_X86_64
#endif
#ifdef MH_DYLINKER
#undef MH_DYLINKER
#endif
#ifdef MH_OBJECT
#undef MH_OBJECT
#endif
#ifdef LC_VERSION_MIN_MACOSX
#undef LC_VERSION_MIN_MACOSX
#endif
#ifdef LC_VERSION_MIN_IPHONEOS
#undef LC_VERSION_MIN_IPHONEOS
#endif
#ifdef LC_VERSION_MIN_TVOS
#undef LC_VERSION_MIN_TVOS
#endif
#ifdef LC_VERSION_MIN_WATCHOS
#undef LC_VERSION_MIN_WATCHOS
#endif
#ifdef LC_BUILD_VERSION
#undef LC_BUILD_VERSION
#endif
#ifdef PLATFORM_MACOS
#undef PLATFORM_MACOS
#endif
#ifdef PLATFORM_MACCATALYST
#undef PLATFORM_MACCATALYST
#endif
#ifdef PLATFORM_IOS
#undef PLATFORM_IOS
#endif
#ifdef PLATFORM_IOSSIMULATOR
#undef PLATFORM_IOSSIMULATOR
#endif
#ifdef PLATFORM_TVOS
#undef PLATFORM_TVOS
#endif
#ifdef PLATFORM_TVOSSIMULATOR
#undef PLATFORM_TVOSSIMULATOR
#endif
#ifdef PLATFORM_WATCHOS
#undef PLATFORM_WATCHOS
#endif
#ifdef PLATFORM_WATCHOSSIMULATOR
#undef PLATFORM_WATCHOSSIMULATOR
#endif

using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;

static constexpr llvm::StringLiteral g_loader_path = "@loader_path";
static constexpr llvm::StringLiteral g_executable_path = "@executable_path";

LLDB_PLUGIN_DEFINE(ObjectFileMachO)

/// Read a Mach-O load-command header (cmd + cmdsize) from \p data at
/// \p offset into \p cmd, advancing \p offset by 8 bytes.  \p T may be
/// \c llvm::MachO::load_command or any of its richer variants
/// (\c thread_command, \c dylib_command, \c encryption_info_command, ...);
/// only the leading cmd/cmdsize fields are touched by this read.  Returns
/// false on EOF or on a cmdsize smaller than sizeof(load_command), in which
/// case callers should break out of their load-command loop to avoid spinning
/// on malformed input.
template <typename T>
static bool ReadMachOCommand(const DataExtractor &data, lldb::offset_t &offset,
                             T &cmd) {
  static_assert(offsetof(T, cmd) == 0, "T::cmd must be the first field");
  static_assert(offsetof(T, cmdsize) == sizeof(uint32_t),
                "T::cmdsize must immediately follow T::cmd");
  static_assert(std::is_same<decltype(T::cmd), uint32_t>::value,
                "T::cmd must be uint32_t");
  static_assert(std::is_same<decltype(T::cmdsize), uint32_t>::value,
                "T::cmdsize must be uint32_t");
  if (data.GetU32(&offset, &cmd, 2) == nullptr)
    return false;
  if (cmd.cmdsize < sizeof(load_command))
    return false;
  return true;
}

static void PrintRegisterValue(RegisterContext *reg_ctx, const char *name,
                               const char *alt_name, size_t reg_byte_size,
                               Stream &data) {
  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name);
  if (reg_info == nullptr)
    reg_info = reg_ctx->GetRegisterInfoByName(alt_name);
  if (reg_info) {
    lldb_private::RegisterValue reg_value;
    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
      if (reg_info->byte_size >= reg_byte_size)
        data.Write(reg_value.GetBytes(), reg_byte_size);
      else {
        data.Write(reg_value.GetBytes(), reg_info->byte_size);
        for (size_t i = 0, n = reg_byte_size - reg_info->byte_size; i < n; ++i)
          data.PutChar(0);
      }
      return;
    }
  }
  // Just write zeros if all else fails
  for (size_t i = 0; i < reg_byte_size; ++i)
    data.PutChar(0);
}

class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 {
public:
  RegisterContextDarwin_x86_64_Mach(lldb_private::Thread &thread,
                                    const DataExtractor &data)
      : RegisterContextDarwin_x86_64(thread, 0) {
    SetRegisterDataFrom_LC_THREAD(data);
  }

  void InvalidateAllRegisters() override {
    // Do nothing... registers are always valid...
  }

  void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
    lldb::offset_t offset = 0;
    SetError(GPRRegSet, Read, -1);
    SetError(FPURegSet, Read, -1);
    SetError(EXCRegSet, Read, -1);

    while (offset < data.GetByteSize()) {
      int flavor = data.GetU32(&offset);
      if (flavor == 0)
        break;
      uint32_t count = data.GetU32(&offset);
      switch (flavor) {
      case GPRRegSet: {
        uint32_t *gpr_data = reinterpret_cast<uint32_t *>(&gpr.rax);
        for (uint32_t i = 0; i < count && offset < data.GetByteSize(); ++i)
          gpr_data[i] = data.GetU32(&offset);
        SetError(GPRRegSet, Read, 0);
      } break;
      case FPURegSet:
        // TODO: fill in FPU regs....
        SetError(FPURegSet, Read, -1);
        break;
      case EXCRegSet:
        exc.trapno = data.GetU32(&offset);
        exc.err = data.GetU32(&offset);
        exc.faultvaddr = data.GetU64(&offset);
        SetError(EXCRegSet, Read, 0);
        break;
      default:
        offset += count * 4;
        break;
      }
    }
  }

  static bool Create_LC_THREAD(Thread *thread, Stream &data) {
    RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
    if (reg_ctx_sp) {
      RegisterContext *reg_ctx = reg_ctx_sp.get();

      data.PutHex32(GPRRegSet); // Flavor
      data.PutHex32(GPRWordCount);
      PrintRegisterValue(reg_ctx, "rax", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rbx", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rcx", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rdx", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rdi", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rsi", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rbp", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rsp", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r8", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r9", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r10", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r11", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r12", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r13", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r14", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "r15", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rip", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "rflags", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "cs", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "fs", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "gs", nullptr, 8, data);

      //            // Write out the FPU registers
      //            const size_t fpu_byte_size = sizeof(FPU);
      //            size_t bytes_written = 0;
      //            data.PutHex32 (FPURegSet);
      //            data.PutHex32 (fpu_byte_size/sizeof(uint64_t));
      //            bytes_written += data.PutHex32(0); // uint32_t pad[0]
      //            bytes_written += data.PutHex32(0); // uint32_t pad[1]
      //            bytes_written += WriteRegister (reg_ctx, "fcw", "fctrl", 2,
      //            data);   // uint16_t    fcw;    // "fctrl"
      //            bytes_written += WriteRegister (reg_ctx, "fsw" , "fstat", 2,
      //            data);  // uint16_t    fsw;    // "fstat"
      //            bytes_written += WriteRegister (reg_ctx, "ftw" , "ftag", 1,
      //            data);   // uint8_t     ftw;    // "ftag"
      //            bytes_written += data.PutHex8  (0); // uint8_t pad1;
      //            bytes_written += WriteRegister (reg_ctx, "fop" , NULL, 2,
      //            data);     // uint16_t    fop;    // "fop"
      //            bytes_written += WriteRegister (reg_ctx, "fioff", "ip", 4,
      //            data);    // uint32_t    ip;     // "fioff"
      //            bytes_written += WriteRegister (reg_ctx, "fiseg", NULL, 2,
      //            data);    // uint16_t    cs;     // "fiseg"
      //            bytes_written += data.PutHex16 (0); // uint16_t    pad2;
      //            bytes_written += WriteRegister (reg_ctx, "dp", "fooff" , 4,
      //            data);   // uint32_t    dp;     // "fooff"
      //            bytes_written += WriteRegister (reg_ctx, "foseg", NULL, 2,
      //            data);    // uint16_t    ds;     // "foseg"
      //            bytes_written += data.PutHex16 (0); // uint16_t    pad3;
      //            bytes_written += WriteRegister (reg_ctx, "mxcsr", NULL, 4,
      //            data);    // uint32_t    mxcsr;
      //            bytes_written += WriteRegister (reg_ctx, "mxcsrmask", NULL,
      //            4, data);// uint32_t    mxcsrmask;
      //            bytes_written += WriteRegister (reg_ctx, "stmm0", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm1", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm2", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm3", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm4", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm5", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm6", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "stmm7", NULL,
      //            sizeof(MMSReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm0" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm1" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm2" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm3" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm4" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm5" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm6" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm7" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm8" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm9" , NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm10", NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm11", NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm12", NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm13", NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm14", NULL,
      //            sizeof(XMMReg), data);
      //            bytes_written += WriteRegister (reg_ctx, "xmm15", NULL,
      //            sizeof(XMMReg), data);
      //
      //            // Fill rest with zeros
      //            for (size_t i=0, n = fpu_byte_size - bytes_written; i<n; ++
      //            i)
      //                data.PutChar(0);

      // Write out the EXC registers
      data.PutHex32(EXCRegSet);
      data.PutHex32(EXCWordCount);
      PrintRegisterValue(reg_ctx, "trapno", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "err", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "faultvaddr", nullptr, 8, data);
      return true;
    }
    return false;
  }

protected:
  int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }

  int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }

  int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }

  int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
    return 0;
  }

  int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
    return 0;
  }

  int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
    return 0;
  }
};

class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm {
public:
  RegisterContextDarwin_arm_Mach(lldb_private::Thread &thread,
                                 const DataExtractor &data)
      : RegisterContextDarwin_arm(thread, 0) {
    SetRegisterDataFrom_LC_THREAD(data);
  }

  void InvalidateAllRegisters() override {
    // Do nothing... registers are always valid...
  }

  void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
    lldb::offset_t offset = 0;
    SetError(GPRRegSet, Read, -1);
    SetError(FPURegSet, Read, -1);
    SetError(EXCRegSet, Read, -1);

    while (offset < data.GetByteSize()) {
      int flavor = data.GetU32(&offset);
      uint32_t count = data.GetU32(&offset);
      offset_t next_thread_state = offset + (count * 4);
      switch (flavor) {
      case GPRAltRegSet:
      case GPRRegSet: {
        // r0-r15, plus CPSR
        uint32_t gpr_buf_count = (sizeof(gpr.r) / sizeof(gpr.r[0])) + 1;
        if (count == gpr_buf_count) {
          for (uint32_t i = 0; i < (count - 1); ++i) {
            gpr.r[i] = data.GetU32(&offset);
          }
          gpr.cpsr = data.GetU32(&offset);

          SetError(GPRRegSet, Read, 0);
        }
      } break;

      case FPURegSet: {
        uint8_t *fpu_reg_buf = (uint8_t *)&fpu.floats;
        const int fpu_reg_buf_size = sizeof(fpu.floats);
        if (data.ExtractBytes(offset, fpu_reg_buf_size, eByteOrderLittle,
                              fpu_reg_buf) == fpu_reg_buf_size) {
          offset += fpu_reg_buf_size;
          fpu.fpscr = data.GetU32(&offset);
          SetError(FPURegSet, Read, 0);
        }
      } break;

      case EXCRegSet:
        if (count == 3) {
          exc.exception = data.GetU32(&offset);
          exc.fsr = data.GetU32(&offset);
          exc.far = data.GetU32(&offset);
          SetError(EXCRegSet, Read, 0);
        }
        break;
      }
      offset = next_thread_state;
    }
  }

  static bool Create_LC_THREAD(Thread *thread, Stream &data) {
    RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
    if (reg_ctx_sp) {
      RegisterContext *reg_ctx = reg_ctx_sp.get();

      data.PutHex32(GPRRegSet); // Flavor
      data.PutHex32(GPRWordCount);
      PrintRegisterValue(reg_ctx, "r0", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r1", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r2", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r3", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r4", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r5", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r6", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r7", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r8", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r9", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r10", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r11", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "r12", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "sp", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "lr", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "pc", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "cpsr", nullptr, 4, data);

      // Write out the EXC registers
      //            data.PutHex32 (EXCRegSet);
      //            data.PutHex32 (EXCWordCount);
      //            WriteRegister (reg_ctx, "exception", NULL, 4, data);
      //            WriteRegister (reg_ctx, "fsr", NULL, 4, data);
      //            WriteRegister (reg_ctx, "far", NULL, 4, data);
      return true;
    }
    return false;
  }

protected:
  int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }

  int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }

  int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }

  int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) override { return -1; }

  int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
    return 0;
  }

  int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
    return 0;
  }

  int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
    return 0;
  }

  int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) override {
    return -1;
  }
};

class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 {
public:
  RegisterContextDarwin_arm64_Mach(lldb_private::Thread &thread,
                                   const DataExtractor &data)
      : RegisterContextDarwin_arm64(thread, 0) {
    SetRegisterDataFrom_LC_THREAD(data);
  }

  void InvalidateAllRegisters() override {
    // Do nothing... registers are always valid...
  }

  void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
    lldb::offset_t offset = 0;
    SetError(GPRRegSet, Read, -1);
    SetError(FPURegSet, Read, -1);
    SetError(EXCRegSet, Read, -1);
    while (offset < data.GetByteSize()) {
      int flavor = data.GetU32(&offset);
      uint32_t count = data.GetU32(&offset);
      offset_t next_thread_state = offset + (count * 4);
      switch (flavor) {
      case GPRRegSet:
        // x0-x29 + fp + lr + sp + pc (== 33 64-bit registers) plus cpsr (1
        // 32-bit register)
        if (count >= (33 * 2) + 1) {
          for (uint32_t i = 0; i < 29; ++i)
            gpr.x[i] = data.GetU64(&offset);
          gpr.fp = data.GetU64(&offset);
          gpr.lr = data.GetU64(&offset);
          gpr.sp = data.GetU64(&offset);
          gpr.pc = data.GetU64(&offset);
          gpr.cpsr = data.GetU32(&offset);
          SetError(GPRRegSet, Read, 0);
        }
        break;
      case FPURegSet: {
        uint8_t *fpu_reg_buf = (uint8_t *)&fpu.v[0];
        const int fpu_reg_buf_size = sizeof(fpu);
        if (fpu_reg_buf_size == count * sizeof(uint32_t) &&
            data.ExtractBytes(offset, fpu_reg_buf_size, eByteOrderLittle,
                              fpu_reg_buf) == fpu_reg_buf_size) {
          SetError(FPURegSet, Read, 0);
        }
      } break;
      case EXCRegSet:
        if (count == 4) {
          exc.far = data.GetU64(&offset);
          exc.esr = data.GetU32(&offset);
          exc.exception = data.GetU32(&offset);
          SetError(EXCRegSet, Read, 0);
        }
        break;
      }
      offset = next_thread_state;
    }
  }

  static bool Create_LC_THREAD(Thread *thread, Stream &data) {
    RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
    if (reg_ctx_sp) {
      RegisterContext *reg_ctx = reg_ctx_sp.get();

      data.PutHex32(GPRRegSet); // Flavor
      data.PutHex32(GPRWordCount);
      PrintRegisterValue(reg_ctx, "x0", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x1", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x2", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x3", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x4", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x5", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x6", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x7", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x8", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x9", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x10", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x11", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x12", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x13", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x14", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x15", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x16", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x17", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x18", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x19", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x20", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x21", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x22", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x23", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x24", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x25", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x26", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x27", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "x28", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "fp", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "lr", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "sp", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "pc", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "cpsr", nullptr, 4, data);
      data.PutHex32(0); // uint32_t pad at the end

      // Write out the EXC registers
      data.PutHex32(EXCRegSet);
      data.PutHex32(EXCWordCount);
      PrintRegisterValue(reg_ctx, "far", nullptr, 8, data);
      PrintRegisterValue(reg_ctx, "esr", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "exception", nullptr, 4, data);
      return true;
    }
    return false;
  }

protected:
  int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }

  int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }

  int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }

  int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) override { return -1; }

  int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
    return 0;
  }

  int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
    return 0;
  }

  int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
    return 0;
  }

  int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) override {
    return -1;
  }
};

class RegisterContextDarwin_riscv32_Mach
    : public RegisterContextDarwin_riscv32 {
public:
  RegisterContextDarwin_riscv32_Mach(lldb_private::Thread &thread,
                                     const DataExtractor &data)
      : RegisterContextDarwin_riscv32(thread, 0) {
    SetRegisterDataFrom_LC_THREAD(data);
  }

  void InvalidateAllRegisters() override {
    // Do nothing... registers are always valid...
  }

  void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
    lldb::offset_t offset = 0;
    SetError(GPRRegSet, Read, -1);
    SetError(FPURegSet, Read, -1);
    SetError(EXCRegSet, Read, -1);
    SetError(CSRRegSet, Read, -1);
    while (offset < data.GetByteSize()) {
      int flavor = data.GetU32(&offset);
      uint32_t count = data.GetU32(&offset);
      offset_t next_thread_state = offset + (count * 4);
      switch (flavor) {
      case GPRRegSet:
        // x0-x31 + pc
        if (count >= 32) {
          for (uint32_t i = 0; i < 32; ++i)
            ((uint32_t *)&gpr.x0)[i] = data.GetU32(&offset);
          gpr.pc = data.GetU32(&offset);
          SetError(GPRRegSet, Read, 0);
        }
        break;
      case FPURegSet: {
        // f0-f31 + fcsr
        if (count >= 32) {
          for (uint32_t i = 0; i < 32; ++i)
            ((uint32_t *)&fpr.f0)[i] = data.GetU32(&offset);
          fpr.fcsr = data.GetU32(&offset);
          SetError(FPURegSet, Read, 0);
        }
      } break;
      case EXCRegSet:
        if (count == 3) {
          exc.exception = data.GetU32(&offset);
          exc.fsr = data.GetU32(&offset);
          exc.far = data.GetU32(&offset);
          SetError(EXCRegSet, Read, 0);
        }
        break;
      }
      offset = next_thread_state;
    }
  }

  static bool Create_LC_THREAD(Thread *thread, Stream &data) {
    RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
    if (reg_ctx_sp) {
      RegisterContext *reg_ctx = reg_ctx_sp.get();

      data.PutHex32(GPRRegSet); // Flavor
      data.PutHex32(GPRWordCount);
      PrintRegisterValue(reg_ctx, "x0", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x1", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x2", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x3", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x4", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x5", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x6", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x7", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x8", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x9", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x10", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x11", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x12", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x13", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x14", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x15", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x16", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x17", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x18", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x19", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x20", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x21", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x22", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x23", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x24", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x25", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x26", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x27", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x28", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x29", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x30", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "x31", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "pc", nullptr, 4, data);
      data.PutHex32(0); // uint32_t pad at the end

      // Write out the EXC registers
      data.PutHex32(EXCRegSet);
      data.PutHex32(EXCWordCount);
      PrintRegisterValue(reg_ctx, "exception", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "fsr", nullptr, 4, data);
      PrintRegisterValue(reg_ctx, "far", nullptr, 4, data);
      return true;
    }
    return false;
  }

protected:
  int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }

  int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }

  int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }

  int DoReadCSR(lldb::tid_t tid, int flavor, CSR &csr) override { return -1; }

  int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
    return 0;
  }

  int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
    return 0;
  }

  int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
    return 0;
  }

  int DoWriteCSR(lldb::tid_t tid, int flavor, const CSR &csr) override {
    return 0;
  }
};

static uint32_t MachHeaderSizeFromMagic(uint32_t magic) {
  switch (magic) {
  case MH_MAGIC:
  case MH_CIGAM:
    return sizeof(struct llvm::MachO::mach_header);

  case MH_MAGIC_64:
  case MH_CIGAM_64:
    return sizeof(struct llvm::MachO::mach_header_64);
    break;

  default:
    break;
  }
  return 0;
}

#define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008

char ObjectFileMachO::ID;

void ObjectFileMachO::Initialize() {
  PluginManager::RegisterPlugin(
      GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
      CreateMemoryInstance, GetModuleSpecifications, SaveCore);
}

void ObjectFileMachO::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

ObjectFile *ObjectFileMachO::CreateInstance(const lldb::ModuleSP &module_sp,
                                            DataExtractorSP extractor_sp,
                                            lldb::offset_t data_offset,
                                            const FileSpec *file,
                                            lldb::offset_t file_offset,
                                            lldb::offset_t length) {
  if (!extractor_sp || !extractor_sp->HasData()) {
    DataBufferSP data_sp = MapFileData(*file, length, file_offset);
    if (!data_sp)
      return nullptr;
    data_offset = 0;
    extractor_sp = std::make_shared<DataExtractor>(data_sp);
  }

  if (!ObjectFileMachO::MagicBytesMatch(extractor_sp, data_offset, length))
    return nullptr;

  // Update the data to contain the entire file if it doesn't already
  if (extractor_sp->GetByteSize() < length) {
    DataBufferSP data_sp = MapFileData(*file, length, file_offset);
    if (!data_sp)
      return nullptr;
    data_offset = 0;
    extractor_sp = std::make_shared<DataExtractor>(data_sp);
  }
  auto objfile_up = std::make_unique<ObjectFileMachO>(
      module_sp, extractor_sp, data_offset, file, file_offset, length);
  if (!objfile_up || !objfile_up->ParseHeader())
    return nullptr;

  return objfile_up.release();
}

ObjectFile *ObjectFileMachO::CreateMemoryInstance(
    const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
    const ProcessSP &process_sp, lldb::addr_t header_addr) {
  DataExtractorSP extractor_sp = std::make_shared<DataExtractor>(data_sp);
  if (ObjectFileMachO::MagicBytesMatch(extractor_sp, 0,
                                       extractor_sp->GetByteSize())) {
    std::unique_ptr<ObjectFile> objfile_up(
        new ObjectFileMachO(module_sp, data_sp, process_sp, header_addr));
    if (objfile_up.get() && objfile_up->ParseHeader())
      return objfile_up.release();
  }
  return nullptr;
}

ModuleSpecList ObjectFileMachO::GetModuleSpecifications(
    const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp,
    lldb::offset_t file_offset, lldb::offset_t length) {
  if (!extractor_sp || !extractor_sp->HasData())
    return {};

  ModuleSpecList specs;
  if (ObjectFileMachO::MagicBytesMatch(extractor_sp, 0,
                                       extractor_sp->GetByteSize())) {
    llvm::MachO::mach_header header;
    offset_t data_offset = 0;
    if (ParseHeader(extractor_sp, &data_offset, header)) {
      size_t header_and_load_cmds =
          header.sizeofcmds + MachHeaderSizeFromMagic(header.magic);
      if (header_and_load_cmds >= extractor_sp->GetByteSize()) {
        DataBufferSP file_data_sp =
            MapFileData(file, header_and_load_cmds, file_offset);
        if (file_data_sp)
          extractor_sp->SetData(file_data_sp);
        data_offset = MachHeaderSizeFromMagic(header.magic);
      }
      if (extractor_sp && extractor_sp->HasData()) {
        ModuleSpec base_spec;
        base_spec.GetFileSpec() = file;
        base_spec.SetObjectOffset(file_offset);
        base_spec.SetObjectSize(length);
        GetAllArchSpecs(header, *extractor_sp, data_offset, base_spec, specs);
      }
    }
  }
  return specs;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameTEXT() {
  static constexpr llvm::StringLiteral g_segment_name_TEXT("__TEXT");
  return g_segment_name_TEXT;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameDATA() {
  static constexpr llvm::StringLiteral g_segment_name_DATA("__DATA");
  return g_segment_name_DATA;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameDATA_DIRTY() {
  static constexpr llvm::StringLiteral g_segment_name("__DATA_DIRTY");
  return g_segment_name;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameDATA_CONST() {
  static constexpr llvm::StringLiteral g_segment_name("__DATA_CONST");
  return g_segment_name;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameOBJC() {
  static constexpr llvm::StringLiteral g_segment_name_OBJC("__OBJC");
  return g_segment_name_OBJC;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameLINKEDIT() {
  static constexpr llvm::StringLiteral g_section_name_LINKEDIT("__LINKEDIT");
  return g_section_name_LINKEDIT;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameDWARF() {
  static constexpr llvm::StringLiteral g_section_name("__DWARF");
  return g_section_name;
}

llvm::StringRef ObjectFileMachO::GetSegmentNameLLVM_COV() {
  static constexpr llvm::StringLiteral g_section_name("__LLVM_COV");
  return g_section_name;
}

llvm::StringRef ObjectFileMachO::GetSectionNameEHFrame() {
  static constexpr llvm::StringLiteral g_section_name_eh_frame("__eh_frame");
  return g_section_name_eh_frame;
}

llvm::StringRef ObjectFileMachO::GetSectionNameLLDBNoNlist() {
  static constexpr llvm::StringLiteral g_section_name_lldb_no_nlist(
      "__lldb_no_nlist");
  return g_section_name_lldb_no_nlist;
}

bool ObjectFileMachO::MagicBytesMatch(DataExtractorSP extractor_sp,
                                      lldb::addr_t data_offset,
                                      lldb::addr_t data_length) {
  lldb::offset_t offset = data_offset;
  uint32_t magic = extractor_sp->GetU32(&offset);

  offset += 4; // cputype
  offset += 4; // cpusubtype
  uint32_t filetype = extractor_sp->GetU32(&offset);

  // A fileset has a Mach-O header but is not an
  // individual file and must be handled via an
  // ObjectContainer plugin.
  if (filetype == llvm::MachO::MH_FILESET)
    return false;

  return MachHeaderSizeFromMagic(magic) != 0;
}

ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
                                 DataExtractorSP extractor_sp,
                                 lldb::offset_t data_offset,
                                 const FileSpec *file,
                                 lldb::offset_t file_offset,
                                 lldb::offset_t length)
    : ObjectFile(module_sp, file, file_offset, length, extractor_sp,
                 data_offset),
      m_mach_sections(), m_entry_point_address(), m_thread_context_offsets(),
      m_thread_context_offsets_valid(false), m_reexported_dylibs(),
      m_allow_assembly_emulation_unwind_plans(true) {
  ::memset(&m_header, 0, sizeof(m_header));
  ::memset(&m_dysymtab, 0, sizeof(m_dysymtab));
}

ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp,
                                 lldb::WritableDataBufferSP header_data_sp,
                                 const lldb::ProcessSP &process_sp,
                                 lldb::addr_t header_addr)
    : ObjectFile(module_sp, process_sp, header_addr,
                 std::make_shared<DataExtractor>(header_data_sp)),
      m_mach_sections(), m_entry_point_address(), m_thread_context_offsets(),
      m_thread_context_offsets_valid(false), m_reexported_dylibs(),
      m_allow_assembly_emulation_unwind_plans(true) {
  ::memset(&m_header, 0, sizeof(m_header));
  ::memset(&m_dysymtab, 0, sizeof(m_dysymtab));
}

bool ObjectFileMachO::ParseHeader(DataExtractorSP &extractor_sp,
                                  lldb::offset_t *data_offset_ptr,
                                  llvm::MachO::mach_header &header) {
  extractor_sp->SetByteOrder(endian::InlHostByteOrder());
  // Leave magic in the original byte order
  header.magic = extractor_sp->GetU32(data_offset_ptr);
  bool can_parse = false;
  bool is_64_bit = false;
  switch (header.magic) {
  case MH_MAGIC:
    extractor_sp->SetByteOrder(endian::InlHostByteOrder());
    extractor_sp->SetAddressByteSize(4);
    can_parse = true;
    break;

  case MH_MAGIC_64:
    extractor_sp->SetByteOrder(endian::InlHostByteOrder());
    extractor_sp->SetAddressByteSize(8);
    can_parse = true;
    is_64_bit = true;
    break;

  case MH_CIGAM:
    extractor_sp->SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig
                                   ? eByteOrderLittle
                                   : eByteOrderBig);
    extractor_sp->SetAddressByteSize(4);
    can_parse = true;
    break;

  case MH_CIGAM_64:
    extractor_sp->SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig
                                   ? eByteOrderLittle
                                   : eByteOrderBig);
    extractor_sp->SetAddressByteSize(8);
    is_64_bit = true;
    can_parse = true;
    break;

  default:
    break;
  }

  if (can_parse) {
    extractor_sp->GetU32(data_offset_ptr, &header.cputype, 6);
    if (is_64_bit)
      *data_offset_ptr += 4;
    return true;
  } else {
    memset(&header, 0, sizeof(header));
  }
  return false;
}

bool ObjectFileMachO::ParseHeader() {
  ModuleSP module_sp(GetModule());
  if (!module_sp)
    return false;

  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
  bool can_parse = false;
  lldb::offset_t offset = 0;
  m_data_nsp->SetByteOrder(endian::InlHostByteOrder());
  // Leave magic in the original byte order
  m_header.magic = m_data_nsp->GetU32(&offset);
  switch (m_header.magic) {
  case MH_MAGIC:
    m_data_nsp->SetByteOrder(endian::InlHostByteOrder());
    m_data_nsp->SetAddressByteSize(4);
    can_parse = true;
    break;

  case MH_MAGIC_64:
    m_data_nsp->SetByteOrder(endian::InlHostByteOrder());
    m_data_nsp->SetAddressByteSize(8);
    can_parse = true;
    break;

  case MH_CIGAM:
    m_data_nsp->SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig
                                 ? eByteOrderLittle
                                 : eByteOrderBig);
    m_data_nsp->SetAddressByteSize(4);
    can_parse = true;
    break;

  case MH_CIGAM_64:
    m_data_nsp->SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig
                                 ? eByteOrderLittle
                                 : eByteOrderBig);
    m_data_nsp->SetAddressByteSize(8);
    can_parse = true;
    break;

  default:
    break;
  }

  if (can_parse) {
    m_data_nsp->GetU32(&offset, &m_header.cputype, 6);

    ModuleSpecList all_specs;
    ModuleSpec base_spec;
    GetAllArchSpecs(m_header, *m_data_nsp,
                    MachHeaderSizeFromMagic(m_header.magic), base_spec,
                    all_specs);

    for (unsigned i = 0, e = all_specs.GetSize(); i != e; ++i) {
      ArchSpec mach_arch =
          all_specs.GetModuleSpecRefAtIndex(i).GetArchitecture();

      // Check if the module has a required architecture
      const ArchSpec &module_arch = module_sp->GetArchitecture();
      if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
        continue;

      if (SetModulesArchitecture(mach_arch)) {
        const size_t header_and_lc_size =
            m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic);
        if (m_data_nsp->GetByteSize() < header_and_lc_size) {
          DataBufferSP data_sp;
          ProcessSP process_sp(m_process_wp.lock());
          if (process_sp) {
            data_sp = ReadMemory(process_sp, m_memory_addr, header_and_lc_size);
          } else {
            // Read in all only the load command data from the file on disk
            data_sp = MapFileData(m_file, header_and_lc_size, m_file_offset);
            if (data_sp->GetByteSize() != header_and_lc_size)
              continue;
          }
          if (data_sp)
            m_data_nsp->SetData(data_sp);
        }
      }
      return true;
    }
    // None found.
    return false;
  } else {
    memset(&m_header, 0, sizeof(struct llvm::MachO::mach_header));
  }
  return false;
}

ByteOrder ObjectFileMachO::GetByteOrder() const {
  return m_data_nsp->GetByteOrder();
}

bool ObjectFileMachO::IsExecutable() const {
  return m_header.filetype == MH_EXECUTE;
}

bool ObjectFileMachO::IsDynamicLoader() const {
  return m_header.filetype == MH_DYLINKER;
}

bool ObjectFileMachO::IsSharedCacheBinary() const {
  return m_header.flags & MH_DYLIB_IN_CACHE;
}

bool ObjectFileMachO::IsKext() const {
  return m_header.filetype == MH_KEXT_BUNDLE;
}

uint32_t ObjectFileMachO::GetAddressByteSize() const {
  return m_data_nsp->GetAddressByteSize();
}

AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
  Symtab *symtab = GetSymtab();
  if (!symtab)
    return AddressClass::eUnknown;

  const Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
  if (symbol) {
    if (symbol->ValueIsAddress()) {
      SectionSP section_sp(symbol->GetAddressRef().GetSection());
      if (section_sp) {
        const lldb::SectionType section_type = section_sp->GetType();
        switch (section_type) {
        case eSectionTypeInvalid:
          return AddressClass::eUnknown;

        case eSectionTypeCode:
          if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) {
            // For ARM we have a bit in the n_desc field of the symbol that
            // tells us ARM/Thumb which is bit 0x0008.
            if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB)
              return AddressClass::eCodeAlternateISA;
          }
          return AddressClass::eCode;

        case eSectionTypeContainer:
          return AddressClass::eUnknown;

        case eSectionTypeData:
        case eSectionTypeDataCString:
        case eSectionTypeDataCStringPointers:
        case eSectionTypeDataSymbolAddress:
        case eSectionTypeData4:
        case eSectionTypeData8:
        case eSectionTypeData16:
        case eSectionTypeDataPointers:
        case eSectionTypeZeroFill:
        case eSectionTypeDataObjCMessageRefs:
        case eSectionTypeDataObjCCFStrings:
        case eSectionTypeGoSymtab:
        case eSectionTypeWasmName:
        case eSectionTypeWasmGlobal:
          return AddressClass::eData;

        case eSectionTypeDebug:
        case eSectionTypeDWARFDebugAbbrev:
        case eSectionTypeDWARFDebugAbbrevDwo:
        case eSectionTypeDWARFDebugAddr:
        case eSectionTypeDWARFDebugAranges:
        case eSectionTypeDWARFDebugCuIndex:
        case eSectionTypeDWARFDebugFrame:
        case eSectionTypeDWARFDebugInfo:
        case eSectionTypeDWARFDebugInfoDwo:
        case eSectionTypeDWARFDebugLine:
        case eSectionTypeDWARFDebugLineStr:
        case eSectionTypeDWARFDebugLoc:
        case eSectionTypeDWARFDebugLocDwo:
        case eSectionTypeDWARFDebugLocLists:
        case eSectionTypeDWARFDebugLocListsDwo:
        case eSectionTypeDWARFDebugMacInfo:
        case eSectionTypeDWARFDebugMacro:
        case eSectionTypeDWARFDebugNames:
        case eSectionTypeDWARFDebugPubNames:
        case eSectionTypeDWARFDebugPubTypes:
        case eSectionTypeDWARFDebugRanges:
        case eSectionTypeDWARFDebugRngLists:
        case eSectionTypeDWARFDebugRngListsDwo:
        case eSectionTypeDWARFDebugStr:
        case eSectionTypeDWARFDebugStrDwo:
        case eSectionTypeDWARFDebugStrOffsets:
        case eSectionTypeDWARFDebugStrOffsetsDwo:
        case eSectionTypeDWARFDebugTuIndex:
        case eSectionTypeDWARFDebugTypes:
        case eSectionTypeDWARFDebugTypesDwo:
        case eSectionTypeDWARFAppleNames:
        case eSectionTypeDWARFAppleTypes:
        case eSectionTypeDWARFAppleNamespaces:
        case eSectionTypeDWARFAppleObjC:
        case eSectionTypeDWARFGNUDebugAltLink:
        case eSectionTypeCTF:
        case eSectionTypeLLDBTypeSummaries:
        case eSectionTypeLLDBFormatters:
        case eSectionTypeSwiftModules:
          return AddressClass::eDebug;

        case eSectionTypeEHFrame:
        case eSectionTypeARMexidx:
        case eSectionTypeARMextab:
        case eSectionTypeCompactUnwind:
          return AddressClass::eRuntime;

        case eSectionTypeAbsoluteAddress:
        case eSectionTypeELFSymbolTable:
        case eSectionTypeELFDynamicSymbols:
        case eSectionTypeELFRelocationEntries:
        case eSectionTypeELFDynamicLinkInfo:
        case eSectionTypeOther:
          return AddressClass::eUnknown;
        }
      }
    }

    const SymbolType symbol_type = symbol->GetType();
    switch (symbol_type) {
    case eSymbolTypeAny:
      return AddressClass::eUnknown;
    case eSymbolTypeAbsolute:
      return AddressClass::eUnknown;

    case eSymbolTypeCode:
    case eSymbolTypeTrampoline:
    case eSymbolTypeResolver:
      if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) {
        // For ARM we have a bit in the n_desc field of the symbol that tells
        // us ARM/Thumb which is bit 0x0008.
        if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB)
          return AddressClass::eCodeAlternateISA;
      }
      return AddressClass::eCode;

    case eSymbolTypeData:
      return AddressClass::eData;
    case eSymbolTypeRuntime:
      return AddressClass::eRuntime;
    case eSymbolTypeException:
      return AddressClass::eRuntime;
    case eSymbolTypeSourceFile:
      return AddressClass::eDebug;
    case eSymbolTypeHeaderFile:
      return AddressClass::eDebug;
    case eSymbolTypeObjectFile:
      return AddressClass::eDebug;
    case eSymbolTypeCommonBlock:
      return AddressClass::eDebug;
    case eSymbolTypeBlock:
      return AddressClass::eDebug;
    case eSymbolTypeLocal:
      return AddressClass::eData;
    case eSymbolTypeParam:
      return AddressClass::eData;
    case eSymbolTypeVariable:
      return AddressClass::eData;
    case eSymbolTypeVariableType:
      return AddressClass::eDebug;
    case eSymbolTypeLineEntry:
      return AddressClass::eDebug;
    case eSymbolTypeLineHeader:
      return AddressClass::eDebug;
    case eSymbolTypeScopeBegin:
      return AddressClass::eDebug;
    case eSymbolTypeScopeEnd:
      return AddressClass::eDebug;
    case eSymbolTypeAdditional:
      return AddressClass::eUnknown;
    case eSymbolTypeCompiler:
      return AddressClass::eDebug;
    case eSymbolTypeInstrumentation:
      return AddressClass::eDebug;
    case eSymbolTypeUndefined:
      return AddressClass::eUnknown;
    case eSymbolTypeObjCClass:
      return AddressClass::eRuntime;
    case eSymbolTypeObjCMetaClass:
      return AddressClass::eRuntime;
    case eSymbolTypeObjCIVar:
      return AddressClass::eRuntime;
    case eSymbolTypeReExported:
      return AddressClass::eRuntime;
    }
  }
  return AddressClass::eUnknown;
}

bool ObjectFileMachO::IsStripped() {
  if (m_dysymtab.cmd == 0) {
    ModuleSP module_sp(GetModule());
    if (module_sp) {
      lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
      for (uint32_t i = 0; i < m_header.ncmds; ++i) {
        const lldb::offset_t load_cmd_offset = offset;

        llvm::MachO::load_command lc = {};
        if (!ReadMachOCommand(*m_data_nsp, offset, lc))
          break;
        if (lc.cmd == LC_DYSYMTAB) {
          m_dysymtab.cmd = lc.cmd;
          m_dysymtab.cmdsize = lc.cmdsize;
          if (m_data_nsp->GetU32(&offset, &m_dysymtab.ilocalsym,
                                 (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2) ==
              nullptr) {
            // Clear m_dysymtab if we were unable to read all items from the
            // load command
            ::memset(&m_dysymtab, 0, sizeof(m_dysymtab));
          }
        }
        offset = load_cmd_offset + lc.cmdsize;
      }
    }
  }
  if (m_dysymtab.cmd)
    return m_dysymtab.nlocalsym <= 1;
  return false;
}

ObjectFileMachO::EncryptedFileRanges ObjectFileMachO::GetEncryptedFileRanges() {
  EncryptedFileRanges result;
  lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);

  llvm::MachO::encryption_info_command encryption_cmd;
  for (uint32_t i = 0; i < m_header.ncmds; ++i) {
    const lldb::offset_t load_cmd_offset = offset;
    if (!ReadMachOCommand(*m_data_nsp, offset, encryption_cmd))
      break;

    // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for the
    // 3 fields we care about, so treat them the same.
    if (encryption_cmd.cmd == LC_ENCRYPTION_INFO ||
        encryption_cmd.cmd == LC_ENCRYPTION_INFO_64) {
      if (m_data_nsp->GetU32(&offset, &encryption_cmd.cryptoff, 3)) {
        if (encryption_cmd.cryptid != 0) {
          EncryptedFileRanges::Entry entry;
          entry.SetRangeBase(encryption_cmd.cryptoff);
          entry.SetByteSize(encryption_cmd.cryptsize);
          result.Append(entry);
        }
      }
    }
    offset = load_cmd_offset + encryption_cmd.cmdsize;
  }

  return result;
}

void ObjectFileMachO::SanitizeSegmentCommand(
    llvm::MachO::segment_command_64 &seg_cmd, uint32_t cmd_idx) {
  if (m_length == 0 || seg_cmd.filesize == 0)
    return;

  if (IsSharedCacheBinary() && !IsInMemory()) {
    // In shared cache images, the load commands are relative to the
    // shared cache file, and not the specific image we are
    // examining. Let's fix this up so that it looks like a normal
    // image.
    llvm::StringRef segname(seg_cmd.segname,
                            strnlen(seg_cmd.segname, sizeof(seg_cmd.segname)));
    if (segname == GetSegmentNameTEXT())
      m_text_address = seg_cmd.vmaddr;
    if (segname == GetSegmentNameLINKEDIT())
      m_linkedit_original_offset = seg_cmd.fileoff;

    seg_cmd.fileoff = seg_cmd.vmaddr - m_text_address;
  }

  if (seg_cmd.fileoff > m_length) {
    // We have a load command that says it extends past the end of the file.
    // This is likely a corrupt file.  We don't have any way to return an error
    // condition here (this method was likely invoked from something like
    // ObjectFile::GetSectionList()), so we just null out the section contents,
    // and dump a message to stdout.  The most common case here is core file
    // debugging with a truncated file.
    const char *lc_segment_name =
        seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
    GetModule()->ReportWarning(
        "load command {0} {1} has a fileoff ({2:x16}) that extends beyond "
        "the end of the file ({3:x16}), ignoring this section",
        cmd_idx, lc_segment_name, seg_cmd.fileoff, m_length);

    seg_cmd.fileoff = 0;
    seg_cmd.filesize = 0;
  }

  if (seg_cmd.fileoff + seg_cmd.filesize > m_length) {
    // We have a load command that says it extends past the end of the file.
    // This is likely a corrupt file.  We don't have any way to return an error
    // condition here (this method was likely invoked from something like
    // ObjectFile::GetSectionList()), so we just null out the section contents,
    // and dump a message to stdout.  The most common case here is core file
    // debugging with a truncated file.
    const char *lc_segment_name =
        seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
    GetModule()->ReportWarning(
        "load command {0} {1} has a fileoff + filesize ({2:x16}) that "
        "extends beyond the end of the file ({3:x16}), the segment will be "
        "truncated to match",
        cmd_idx, lc_segment_name, seg_cmd.fileoff + seg_cmd.filesize, m_length);

    // Truncate the length
    seg_cmd.filesize = m_length - seg_cmd.fileoff;
  }
}

static uint32_t
GetSegmentPermissions(const llvm::MachO::segment_command_64 &seg_cmd) {
  uint32_t result = 0;
  if (seg_cmd.initprot & VM_PROT_READ)
    result |= ePermissionsReadable;
  if (seg_cmd.initprot & VM_PROT_WRITE)
    result |= ePermissionsWritable;
  if (seg_cmd.initprot & VM_PROT_EXECUTE)
    result |= ePermissionsExecutable;
  return result;
}

static lldb::SectionType GetSectionType(uint32_t flags,
                                        llvm::StringRef section_name) {

  if (flags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS))
    return eSectionTypeCode;

  uint32_t mach_sect_type = flags & SECTION_TYPE;
  static constexpr llvm::StringLiteral g_sect_name_objc_data("__objc_data");
  static constexpr llvm::StringLiteral g_sect_name_objc_msgrefs(
      "__objc_msgrefs");
  static constexpr llvm::StringLiteral g_sect_name_objc_selrefs(
      "__objc_selrefs");
  static constexpr llvm::StringLiteral g_sect_name_objc_classrefs(
      "__objc_classrefs");
  static constexpr llvm::StringLiteral g_sect_name_objc_superrefs(
      "__objc_superrefs");
  static constexpr llvm::StringLiteral g_sect_name_objc_const("__objc_const");
  static constexpr llvm::StringLiteral g_sect_name_objc_classlist(
      "__objc_classlist");
  static constexpr llvm::StringLiteral g_sect_name_cfstring("__cfstring");

  static constexpr llvm::StringLiteral g_sect_name_dwarf_debug_str_offs(
      "__debug_str_offs");
  static constexpr llvm::StringLiteral g_sect_name_dwarf_debug_str_offs_dwo(
      "__debug_str_offs.dwo");
  static constexpr llvm::StringLiteral g_sect_name_dwarf_apple_names(
      "__apple_names");
  static constexpr llvm::StringLiteral g_sect_name_dwarf_apple_types(
      "__apple_types");
  static constexpr llvm::StringLiteral g_sect_name_dwarf_apple_namespaces(
      "__apple_namespac");
  static constexpr llvm::StringLiteral g_sect_name_dwarf_apple_objc(
      "__apple_objc");
  static constexpr llvm::StringLiteral g_sect_name_eh_frame("__eh_frame");
  static constexpr llvm::StringLiteral g_sect_name_compact_unwind(
      "__unwind_info");
  static constexpr llvm::StringLiteral g_sect_name_text("__text");
  static constexpr llvm::StringLiteral g_sect_name_data("__data");
  static constexpr llvm::StringLiteral g_sect_name_go_symtab("__gosymtab");
  static constexpr llvm::StringLiteral g_sect_name_ctf("__ctf");
  static constexpr llvm::StringLiteral g_sect_name_lldb_summaries(
      "__lldbsummaries");
  static constexpr llvm::StringLiteral g_sect_name_lldb_formatters(
      "__lldbformatters");
  static constexpr llvm::StringLiteral g_sect_name_swift_ast("__swift_ast");

  if (section_name == g_sect_name_dwarf_debug_str_offs)
    return eSectionTypeDWARFDebugStrOffsets;
  if (section_name == g_sect_name_dwarf_debug_str_offs_dwo)
    return eSectionTypeDWARFDebugStrOffsetsDwo;

  llvm::StringRef stripped_name = section_name;
  if (stripped_name.consume_front("__debug_"))
    return ObjectFile::GetDWARFSectionTypeFromName(stripped_name);

  if (section_name == g_sect_name_dwarf_apple_names)
    return eSectionTypeDWARFAppleNames;
  if (section_name == g_sect_name_dwarf_apple_types)
    return eSectionTypeDWARFAppleTypes;
  if (section_name == g_sect_name_dwarf_apple_namespaces)
    return eSectionTypeDWARFAppleNamespaces;
  if (section_name == g_sect_name_dwarf_apple_objc)
    return eSectionTypeDWARFAppleObjC;
  if (section_name == g_sect_name_objc_selrefs)
    return eSectionTypeDataCStringPointers;
  if (section_name == g_sect_name_objc_msgrefs)
    return eSectionTypeDataObjCMessageRefs;
  if (section_name == g_sect_name_eh_frame)
    return eSectionTypeEHFrame;
  if (section_name == g_sect_name_compact_unwind)
    return eSectionTypeCompactUnwind;
  if (section_name == g_sect_name_cfstring)
    return eSectionTypeDataObjCCFStrings;
  if (section_name == g_sect_name_go_symtab)
    return eSectionTypeGoSymtab;
  if (section_name == g_sect_name_ctf)
    return eSectionTypeCTF;
  if (section_name == g_sect_name_lldb_summaries)
    return lldb::eSectionTypeLLDBTypeSummaries;
  if (section_name == g_sect_name_lldb_formatters)
    return lldb::eSectionTypeLLDBFormatters;
  if (section_name == g_sect_name_swift_ast)
    return eSectionTypeSwiftModules;
  if (section_name == g_sect_name_objc_data ||
      section_name == g_sect_name_objc_classrefs ||
      section_name == g_sect_name_objc_superrefs ||
      section_name == g_sect_name_objc_const ||
      section_name == g_sect_name_objc_classlist) {
    return eSectionTypeDataPointers;
  }

  switch (mach_sect_type) {
  // TODO: categorize sections by other flags for regular sections
  case S_REGULAR:
    if (section_name == g_sect_name_text)
      return eSectionTypeCode;
    if (section_name == g_sect_name_data)
      return eSectionTypeData;
    return eSectionTypeOther;
  case S_ZEROFILL:
    return eSectionTypeZeroFill;
  case S_CSTRING_LITERALS: // section with only literal C strings
    return eSectionTypeDataCString;
  case S_4BYTE_LITERALS: // section with only 4 byte literals
    return eSectionTypeData4;
  case S_8BYTE_LITERALS: // section with only 8 byte literals
    return eSectionTypeData8;
  case S_LITERAL_POINTERS: // section with only pointers to literals
    return eSectionTypeDataPointers;
  case S_NON_LAZY_SYMBOL_POINTERS: // section with only non-lazy symbol pointers
    return eSectionTypeDataPointers;
  case S_LAZY_SYMBOL_POINTERS: // section with only lazy symbol pointers
    return eSectionTypeDataPointers;
  case S_SYMBOL_STUBS: // section with only symbol stubs, byte size of stub in
                       // the reserved2 field
    return eSectionTypeCode;
  case S_MOD_INIT_FUNC_POINTERS: // section with only function pointers for
                                 // initialization
    return eSectionTypeDataPointers;
  case S_MOD_TERM_FUNC_POINTERS: // section with only function pointers for
                                 // termination
    return eSectionTypeDataPointers;
  case S_COALESCED:
    return eSectionTypeOther;
  case S_GB_ZEROFILL:
    return eSectionTypeZeroFill;
  case S_INTERPOSING: // section with only pairs of function pointers for
                      // interposing
    return eSectionTypeCode;
  case S_16BYTE_LITERALS: // section with only 16 byte literals
    return eSectionTypeData16;
  case S_DTRACE_DOF:
    return eSectionTypeDebug;
  case S_LAZY_DYLIB_SYMBOL_POINTERS:
    return eSectionTypeDataPointers;
  default:
    return eSectionTypeOther;
  }
}

struct ObjectFileMachO::SegmentParsingContext {
  const EncryptedFileRanges EncryptedRanges;
  lldb_private::SectionList &UnifiedList;
  uint32_t NextSegmentIdx = 0;
  uint32_t NextSectionIdx = 0;
  bool FileAddressesChanged = false;

  SegmentParsingContext(EncryptedFileRanges EncryptedRanges,
                        lldb_private::SectionList &UnifiedList)
      : EncryptedRanges(std::move(EncryptedRanges)), UnifiedList(UnifiedList) {}
};

void ObjectFileMachO::ProcessSegmentCommand(
    const llvm::MachO::load_command &load_cmd_, lldb::offset_t offset,
    uint32_t cmd_idx, SegmentParsingContext &context) {
  llvm::MachO::segment_command_64 load_cmd;
  memcpy(&load_cmd, &load_cmd_, sizeof(load_cmd_));

  if (!m_data_nsp->GetU8(&offset, (uint8_t *)load_cmd.segname, 16))
    return;

  ModuleSP module_sp = GetModule();
  const bool is_core = GetType() == eTypeCoreFile;
  const bool is_dsym = (m_header.filetype == MH_DSYM);
  bool add_section = true;
  bool add_to_unified = true;
  llvm::StringRef segname(load_cmd.segname,
                          strnlen(load_cmd.segname, sizeof(load_cmd.segname)));

  SectionSP unified_section_sp(context.UnifiedList.FindSectionByName(segname));
  if (is_dsym && unified_section_sp) {
    if (segname == GetSegmentNameLINKEDIT()) {
      // We need to keep the __LINKEDIT segment private to this object file
      // only
      add_to_unified = false;
    } else {
      // This is the dSYM file and this section has already been created by the
      // object file, no need to create it.
      add_section = false;
    }
  }
  load_cmd.vmaddr = m_data_nsp->GetAddress(&offset);
  load_cmd.vmsize = m_data_nsp->GetAddress(&offset);
  load_cmd.fileoff = m_data_nsp->GetAddress(&offset);
  load_cmd.filesize = m_data_nsp->GetAddress(&offset);
  if (!m_data_nsp->GetU32(&offset, &load_cmd.maxprot, 4))
    return;

  SanitizeSegmentCommand(load_cmd, cmd_idx);

  const uint32_t segment_permissions = GetSegmentPermissions(load_cmd);
  const bool segment_is_encrypted =
      (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0;

  // Use a segment ID of the segment index shifted left by 8 so they never
  // conflict with any of the sections.
  SectionSP segment_sp;
  if (add_section && (!segname.empty() || is_core)) {
    segment_sp = std::make_shared<Section>(
        module_sp, // Module to which this section belongs
        this,      // Object file to which this sections belongs
        ++context.NextSegmentIdx
            << 8, // Section ID is the 1 based segment index
        // shifted right by 8 bits as not to collide with any of the 256
        // section IDs that are possible
        segname.str(),         // Name of this section
        eSectionTypeContainer, // This section is a container of other
        // sections.
        load_cmd.vmaddr, // File VM address == addresses as they are
        // found in the object file
        load_cmd.vmsize,  // VM size in bytes of this section
        load_cmd.fileoff, // Offset to the data for this section in
        // the file
        load_cmd.filesize, // Size in bytes of this section as found
        // in the file
        0,               // Segments have no alignment information
        load_cmd.flags); // Flags for this section

    segment_sp->SetIsEncrypted(segment_is_encrypted);
    m_sections_up->AddSection(segment_sp);
    segment_sp->SetPermissions(segment_permissions);
    if (add_to_unified)
      context.UnifiedList.AddSection(segment_sp);
  } else if (unified_section_sp) {
    // If this is a dSYM and the file addresses in the dSYM differ from the
    // file addresses in the ObjectFile, we must use the file base address for
    // the Section from the dSYM for the DWARF to resolve correctly.
    // This only happens with binaries in the shared cache in practice;
    // normally a mismatch like this would give a binary & dSYM that do not
    // match UUIDs. When a binary is included in the shared cache, its
    // segments are rearranged to optimize the shared cache, so its file
    // addresses will differ from what the ObjectFile had originally,
    // and what the dSYM has.
    if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
      LLDB_LOG(GetLog(LLDBLog::Symbols),
               "Installing dSYM's {0} segment file address over ObjectFile's "
               "so symbol table/debug info resolves correctly for {1}",
               segname, module_sp->GetFileSpec().GetFilename());

      // Make sure we've parsed the symbol table from the ObjectFile before
      // we go around changing its Sections.
      module_sp->GetObjectFile()->GetSymtab();
      // eh_frame would present the same problems but we parse that on a per-
      // function basis as-needed so it's more difficult to remove its use of
      // the Sections.  Realistically, the environments where this code path
      // will be taken will not have eh_frame sections.

      unified_section_sp->SetFileAddress(load_cmd.vmaddr);

      // Notify the module that the section addresses have been changed once
      // we're done so any file-address caches can be updated.
      context.FileAddressesChanged = true;
    }
    m_sections_up->AddSection(unified_section_sp);
  }

  llvm::MachO::section_64 sect64;
  ::memset(&sect64, 0, sizeof(sect64));
  // Push a section into our mach sections for the section at index zero
  // (NO_SECT) if we don't have any mach sections yet...
  if (m_mach_sections.empty())
    m_mach_sections.push_back(sect64);
  uint32_t segment_sect_idx;
  const lldb::user_id_t first_segment_sectID = context.NextSectionIdx + 1;

  // 64 bit mach-o files have sections with 32 bit file offsets. If any section
  // data end will exceed UINT32_MAX, then we need to do some bookkeeping to
  // ensure we can access this data correctly.
  uint64_t section_offset_adjust = 0;
  const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
  for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects;
       ++segment_sect_idx) {
    if (m_data_nsp->GetU8(&offset, (uint8_t *)sect64.sectname,
                          sizeof(sect64.sectname)) == nullptr)
      break;
    if (m_data_nsp->GetU8(&offset, (uint8_t *)sect64.segname,
                          sizeof(sect64.segname)) == nullptr)
      break;
    sect64.addr = m_data_nsp->GetAddress(&offset);
    sect64.size = m_data_nsp->GetAddress(&offset);

    if (m_data_nsp->GetU32(&offset, &sect64.offset, num_u32s) == nullptr)
      break;

    if (IsSharedCacheBinary() && !IsInMemory()) {
      sect64.offset = sect64.addr - m_text_address;
    }

    // Keep a list of mach sections around in case we need to get at data that
    // isn't stored in the abstracted Sections.
    m_mach_sections.push_back(sect64);

    // Make sure we can load sections in mach-o files where some sections cross
    // a 4GB boundary. llvm::MachO::section_64 have only 32 bit file offsets
    // for the file offset of the section contents, so we need to track and
    // sections that overflow and adjust the offsets accordingly.
    const uint64_t section_file_offset =
        (uint64_t)sect64.offset + section_offset_adjust;
    const uint64_t end_section_offset = (uint64_t)sect64.offset + sect64.size;
    if (end_section_offset >= UINT32_MAX)
      section_offset_adjust += end_section_offset & 0xFFFFFFFF00000000ull;

    if (add_section) {
      llvm::StringRef section_name(
          sect64.sectname, strnlen(sect64.sectname, sizeof(sect64.sectname)));
      if (segname.empty()) {
        // We have a segment with no name so we need to conjure up segments
        // that correspond to the section's segname if there isn't already such
        // a section. If there is such a section, we resize the section so that
        // it spans all sections.  We also mark these sections as fake so
        // address matches don't hit if they land in the gaps between the child
        // sections.
        segname = llvm::StringRef(
            sect64.segname, strnlen(sect64.segname, sizeof(sect64.segname)));
        segment_sp = context.UnifiedList.FindSectionByName(segname);
        if (segment_sp.get()) {
          Section *segment = segment_sp.get();
          // Grow the section size as needed.
          const lldb::addr_t sect64_min_addr = sect64.addr;
          const lldb::addr_t sect64_max_addr = sect64_min_addr + sect64.size;
          const lldb::addr_t curr_seg_byte_size = segment->GetByteSize();
          const lldb::addr_t curr_seg_min_addr = segment->GetFileAddress();
          const lldb::addr_t curr_seg_max_addr =
              curr_seg_min_addr + curr_seg_byte_size;
          if (sect64_min_addr >= curr_seg_min_addr) {
            const lldb::addr_t new_seg_byte_size =
                sect64_max_addr - curr_seg_min_addr;
            // Only grow the section size if needed
            if (new_seg_byte_size > curr_seg_byte_size)
              segment->SetByteSize(new_seg_byte_size);
          } else {
            // We need to change the base address of the segment and adjust the
            // child section offsets for all existing children.
            const lldb::addr_t slide_amount =
                sect64_min_addr - curr_seg_min_addr;
            segment->Slide(slide_amount, false);
            segment->GetChildren().Slide(-slide_amount, false);
            segment->SetByteSize(curr_seg_max_addr - sect64_min_addr);
          }

          // Grow the section size as needed.
          if (section_file_offset) {
            const lldb::addr_t segment_min_file_offset =
                segment->GetFileOffset();
            const lldb::addr_t segment_max_file_offset =
                segment_min_file_offset + segment->GetFileSize();

            const lldb::addr_t section_min_file_offset = section_file_offset;
            const lldb::addr_t section_max_file_offset =
                section_min_file_offset + sect64.size;
            const lldb::addr_t new_file_offset =
                std::min(section_min_file_offset, segment_min_file_offset);
            const lldb::addr_t new_file_size =
                std::max(section_max_file_offset, segment_max_file_offset) -
                new_file_offset;
            segment->SetFileOffset(new_file_offset);
            segment->SetFileSize(new_file_size);
          }
        } else {
          // Create a fake section for the section's named segment
          segment_sp = std::make_shared<Section>(
              segment_sp, // Parent section
              module_sp,  // Module to which this section belongs
              this,       // Object file to which this section belongs
              ++context.NextSegmentIdx
                  << 8, // Section ID is the 1 based segment index
              // shifted right by 8 bits as not to
              // collide with any of the 256 section IDs
              // that are possible
              segname.str(),         // Name of this section
              eSectionTypeContainer, // This section is a container of
              // other sections.
              sect64.addr, // File VM address == addresses as they are
              // found in the object file
              sect64.size,         // VM size in bytes of this section
              section_file_offset, // Offset to the data for this section in
              // the file
              section_file_offset ? sect64.size : 0, // Size in bytes of
              // this section as
              // found in the file
              sect64.align,
              load_cmd.flags); // Flags for this section
          segment_sp->SetIsFake(true);
          segment_sp->SetPermissions(segment_permissions);
          m_sections_up->AddSection(segment_sp);
          if (add_to_unified)
            context.UnifiedList.AddSection(segment_sp);
          segment_sp->SetIsEncrypted(segment_is_encrypted);
        }
      }
      assert(segment_sp.get());

      lldb::SectionType sect_type = GetSectionType(sect64.flags, section_name);

      SectionSP section_sp = std::make_shared<Section>(
          segment_sp, module_sp, this, ++context.NextSectionIdx,
          section_name.str(), sect_type,
          sect64.addr - segment_sp->GetFileAddress(), sect64.size,
          section_file_offset, section_file_offset == 0 ? 0 : sect64.size,
          sect64.align, sect64.flags);
      // Set the section to be encrypted to match the segment

      bool section_is_encrypted = false;
      if (!segment_is_encrypted && load_cmd.filesize != 0)
        section_is_encrypted = context.EncryptedRanges.FindEntryThatContains(
                                   section_file_offset) != nullptr;

      section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted);
      section_sp->SetPermissions(segment_permissions);
      segment_sp->GetChildren().AddSection(section_sp);

      if (segment_sp->IsFake()) {
        segment_sp.reset();
        segname = {};
      }
    }
  }
  if (segment_sp && is_dsym) {
    if (first_segment_sectID <= context.NextSectionIdx) {
      lldb::user_id_t sect_uid;
      for (sect_uid = first_segment_sectID; sect_uid <= context.NextSectionIdx;
           ++sect_uid) {
        SectionSP curr_section_sp(
            segment_sp->GetChildren().FindSectionByID(sect_uid));
        SectionSP next_section_sp;
        if (sect_uid + 1 <= context.NextSectionIdx)
          next_section_sp =
              segment_sp->GetChildren().FindSectionByID(sect_uid + 1);

        if (curr_section_sp.get()) {
          if (curr_section_sp->GetByteSize() == 0) {
            if (next_section_sp.get() != nullptr)
              curr_section_sp->SetByteSize(next_section_sp->GetFileAddress() -
                                           curr_section_sp->GetFileAddress());
            else
              curr_section_sp->SetByteSize(load_cmd.vmsize);
          }
        }
      }
    }
  }
}

void ObjectFileMachO::ProcessDysymtabCommand(
    const llvm::MachO::load_command &load_cmd, lldb::offset_t offset) {
  m_dysymtab.cmd = load_cmd.cmd;
  m_dysymtab.cmdsize = load_cmd.cmdsize;
  m_data_nsp->GetU32(&offset, &m_dysymtab.ilocalsym,
                     (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2);
}

void ObjectFileMachO::CreateSections(SectionList &unified_section_list) {
  if (m_sections_up)
    return;

  m_sections_up = std::make_unique<SectionList>();

  lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
  // bool dump_sections = false;
  ModuleSP module_sp(GetModule());

  offset = MachHeaderSizeFromMagic(m_header.magic);

  SegmentParsingContext context(GetEncryptedFileRanges(), unified_section_list);
  llvm::MachO::load_command load_cmd;
  for (uint32_t i = 0; i < m_header.ncmds; ++i) {
    const lldb::offset_t load_cmd_offset = offset;
    if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
      break;

    if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64)
      ProcessSegmentCommand(load_cmd, offset, i, context);
    else if (load_cmd.cmd == LC_DYSYMTAB)
      ProcessDysymtabCommand(load_cmd, offset);

    offset = load_cmd_offset + load_cmd.cmdsize;
  }

  if (context.FileAddressesChanged && module_sp)
    module_sp->SectionFileAddressesChanged();
}

class MachSymtabSectionInfo {
public:
  MachSymtabSectionInfo(SectionList *section_list)
      : m_section_list(section_list), m_section_infos() {
    // Get the number of sections down to a depth of 1 to include all segments
    // and their sections, but no other sections that may be added for debug
    // map or
    m_section_infos.resize(section_list->GetNumSections(1));
  }

  SectionSP GetSection(uint8_t n_sect, addr_t file_addr) {
    if (n_sect == 0)
      return SectionSP();
    if (n_sect < m_section_infos.size()) {
      if (!m_section_infos[n_sect].section_sp) {
        SectionSP section_sp(m_section_list->FindSectionByID(n_sect));
        m_section_infos[n_sect].section_sp = section_sp;
        if (section_sp) {
          m_section_infos[n_sect].vm_range.SetRangeBase(
              section_sp->GetFileAddress());
          m_section_infos[n_sect].vm_range.SetByteSize(
              section_sp->GetByteSize());
        } else {
          std::string filename = "<unknown>";
          SectionSP first_section_sp(m_section_list->GetSectionAtIndex(0));
          if (first_section_sp)
            filename = first_section_sp->GetObjectFile()->GetFileSpec().GetPath();

          Debugger::ReportError(
              llvm::formatv("unable to find section {0} for a symbol in "
                            "{1}, corrupt file?",
                            n_sect, filename));
        }
      }
      if (m_section_infos[n_sect].vm_range.Contains(file_addr)) {
        // Symbol is in section.
        return m_section_infos[n_sect].section_sp;
      } else if (m_section_infos[n_sect].vm_range.GetByteSize() == 0 &&
                 m_section_infos[n_sect].vm_range.GetRangeBase() == file_addr) {
        // Symbol is in section with zero size, but has the same start address
        // as the section. This can happen with linker symbols (symbols that
        // start with the letter 'l' or 'L'.
        return m_section_infos[n_sect].section_sp;
      }
    }
    return m_section_list->FindSectionContainingFileAddress(file_addr);
  }

protected:
  struct SectionInfo {
    SectionInfo() : vm_range(), section_sp() {}

    Range<addr_t, addr_t> vm_range;
    SectionSP section_sp;
  };
  SectionList *m_section_list;
  std::vector<SectionInfo> m_section_infos;
};

static bool
TryParseV2ObjCMetadataSymbol(const char *&symbol_name,
                             const char *&symbol_name_non_abi_mangled,
                             SymbolType &type) {
  static constexpr llvm::StringLiteral g_objc_v2_prefix_class("_OBJC_CLASS_$_");
  static constexpr llvm::StringLiteral g_objc_v2_prefix_metaclass(
      "_OBJC_METACLASS_$_");
  static constexpr llvm::StringLiteral g_objc_v2_prefix_ivar("_OBJC_IVAR_$_");

  llvm::StringRef symbol_name_ref(symbol_name);
  if (symbol_name_ref.empty())
    return false;

  if (symbol_name_ref.starts_with(g_objc_v2_prefix_class)) {
    symbol_name_non_abi_mangled = symbol_name + 1;
    symbol_name = symbol_name + g_objc_v2_prefix_class.size();
    type = eSymbolTypeObjCClass;
    return true;
  }

  if (symbol_name_ref.starts_with(g_objc_v2_prefix_metaclass)) {
    symbol_name_non_abi_mangled = symbol_name + 1;
    symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
    type = eSymbolTypeObjCMetaClass;
    return true;
  }

  if (symbol_name_ref.starts_with(g_objc_v2_prefix_ivar)) {
    symbol_name_non_abi_mangled = symbol_name + 1;
    symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
    type = eSymbolTypeObjCIVar;
    return true;
  }

  return false;
}

static SymbolType GetSymbolType(const char *&symbol_name,
                                bool &demangled_is_synthesized,
                                const SectionSP &text_section_sp,
                                const SectionSP &data_section_sp,
                                const SectionSP &data_dirty_section_sp,
                                const SectionSP &data_const_section_sp,
                                const SectionSP &symbol_section) {
  SymbolType type = eSymbolTypeInvalid;

  llvm::StringRef symbol_sect_name = symbol_section->GetName();
  if (symbol_section->IsDescendant(text_section_sp.get())) {
    if (symbol_section->IsClear(S_ATTR_PURE_INSTRUCTIONS |
                                S_ATTR_SELF_MODIFYING_CODE |
                                S_ATTR_SOME_INSTRUCTIONS))
      type = eSymbolTypeData;
    else
      type = eSymbolTypeCode;
  } else if (symbol_section->IsDescendant(data_section_sp.get()) ||
             symbol_section->IsDescendant(data_dirty_section_sp.get()) ||
             symbol_section->IsDescendant(data_const_section_sp.get())) {
    if (symbol_sect_name.starts_with("__objc")) {
      type = eSymbolTypeRuntime;

      if (symbol_name) {
        llvm::StringRef symbol_name_ref(symbol_name);
        if (symbol_name_ref.starts_with("OBJC_")) {
          static const llvm::StringRef g_objc_v2_prefix_class("OBJC_CLASS_$_");
          static const llvm::StringRef g_objc_v2_prefix_metaclass(
              "OBJC_METACLASS_$_");
          static const llvm::StringRef g_objc_v2_prefix_ivar("OBJC_IVAR_$_");
          if (symbol_name_ref.starts_with(g_objc_v2_prefix_class)) {
            symbol_name = symbol_name + g_objc_v2_prefix_class.size();
            type = eSymbolTypeObjCClass;
            demangled_is_synthesized = true;
          } else if (symbol_name_ref.starts_with(g_objc_v2_prefix_metaclass)) {
            symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size();
            type = eSymbolTypeObjCMetaClass;
            demangled_is_synthesized = true;
          } else if (symbol_name_ref.starts_with(g_objc_v2_prefix_ivar)) {
            symbol_name = symbol_name + g_objc_v2_prefix_ivar.size();
            type = eSymbolTypeObjCIVar;
            demangled_is_synthesized = true;
          }
        }
      }
    } else if (symbol_sect_name.starts_with("__gcc_except_tab")) {
      type = eSymbolTypeException;
    } else {
      type = eSymbolTypeData;
    }
  } else if (symbol_sect_name.starts_with("__IMPORT")) {
    type = eSymbolTypeTrampoline;
  }
  return type;
}

static std::optional<struct nlist_64>
ParseNList(DataExtractor &nlist_data, lldb::offset_t &nlist_data_offset,
           size_t nlist_byte_size) {
  struct nlist_64 nlist;
  if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, nlist_byte_size))
    return {};
  nlist.n_strx = nlist_data.GetU32_unchecked(&nlist_data_offset);
  nlist.n_type = nlist_data.GetU8_unchecked(&nlist_data_offset);
  nlist.n_sect = nlist_data.GetU8_unchecked(&nlist_data_offset);
  nlist.n_desc = nlist_data.GetU16_unchecked(&nlist_data_offset);
  nlist.n_value = nlist_data.GetAddress_unchecked(&nlist_data_offset);
  return nlist;
}

enum { DebugSymbols = true, NonDebugSymbols = false };

void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
  ModuleSP module_sp(GetModule());
  if (!module_sp)
    return;

  Log *log = GetLog(LLDBLog::Symbols);

  const FileSpec &file = m_file ? m_file : module_sp->GetFileSpec();
  llvm::StringRef file_name = file.GetFilename().nonEmptyOr("<Unknown>");
  LLDB_SCOPED_TIMERF("ObjectFileMachO::ParseSymtab () module = %s",
                     file_name.str().c_str());
  LLDB_LOG(log, "Parsing symbol table for {0}", file_name);
  Progress progress("Parsing symbol table", file_name.str());

  LinkeditDataCommandLargeOffsets function_starts_load_command;
  LinkeditDataCommandLargeOffsets exports_trie_load_command;
  DyldInfoCommandLargeOffsets dyld_info;
  DysymtabCommandLargeOffsets dysymtab(m_dysymtab);
  SymtabCommandLargeOffsets symtab_load_command;
  // The data element of type bool indicates that this entry is thumb
  // code.
  typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;

  // Record the address of every function/data that we add to the symtab.
  // We add symbols to the table in the order of most information (nlist
  // records) to least (function starts), and avoid duplicating symbols
  // via this set.
  llvm::DenseSet<addr_t> symbols_added;

  // We are using a llvm::DenseSet for "symbols_added" so we must be sure we
  // do not add the empty key to the set.
  auto add_symbol_addr = [&symbols_added](lldb::addr_t file_addr) {
    // Don't add the empty key.
    if (file_addr == UINT64_MAX)
      return;
    symbols_added.insert(file_addr);
  };
  FunctionStarts function_starts;
  lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
  uint32_t i;
  FileSpecList dylib_files;
  UUID image_uuid;

  for (i = 0; i < m_header.ncmds; ++i) {
    const lldb::offset_t cmd_offset = offset;
    // Read in the load command and load command size
    llvm::MachO::load_command lc;
    if (!ReadMachOCommand(*m_data_nsp, offset, lc))
      break;
    // Watch for the symbol table load command
    switch (lc.cmd) {
    case LC_SYMTAB: {
      llvm::MachO::symtab_command lc_obj;
      if (m_data_nsp->GetU32(&offset, &lc_obj.symoff, 4)) {
        lc_obj.cmd = lc.cmd;
        lc_obj.cmdsize = lc.cmdsize;
        symtab_load_command = lc_obj;
      }
    } break;

    case LC_DYLD_INFO:
    case LC_DYLD_INFO_ONLY: {
      llvm::MachO::dyld_info_command lc_obj;
      if (m_data_nsp->GetU32(&offset, &lc_obj.rebase_off, 10)) {
        lc_obj.cmd = lc.cmd;
        lc_obj.cmdsize = lc.cmdsize;
        dyld_info = lc_obj;
      }
    } break;

    case LC_LOAD_DYLIB:
    case LC_LOAD_WEAK_DYLIB:
    case LC_REEXPORT_DYLIB:
    case LC_LOADFVMLIB:
    case LC_LOAD_UPWARD_DYLIB: {
      uint32_t name_offset = cmd_offset + m_data_nsp->GetU32(&offset);
      if (std::optional<llvm::StringRef> path =
              m_data_nsp->PeekCStr(name_offset)) {
        FileSpec file_spec(*path);
        // Strip the path if there is @rpath, @executable, etc so we just use
        // the basename
        if (path->starts_with("@"))
          file_spec.ClearDirectory();

        if (lc.cmd == LC_REEXPORT_DYLIB) {
          m_reexported_dylibs.AppendIfUnique(file_spec);
        }

        dylib_files.Append(file_spec);
      }
    } break;

    case LC_DYLD_EXPORTS_TRIE: {
      llvm::MachO::linkedit_data_command lc_obj;
      lc_obj.cmd = lc.cmd;
      lc_obj.cmdsize = lc.cmdsize;
      if (m_data_nsp->GetU32(&offset, &lc_obj.dataoff, 2))
        exports_trie_load_command = lc_obj;
    } break;
    case LC_FUNCTION_STARTS: {
      llvm::MachO::linkedit_data_command lc_obj;
      lc_obj.cmd = lc.cmd;
      lc_obj.cmdsize = lc.cmdsize;
      if (m_data_nsp->GetU32(&offset, &lc_obj.dataoff, 2))
        function_starts_load_command = lc_obj;
    } break;

    case LC_UUID: {
      const uint8_t *uuid_bytes = m_data_nsp->PeekData(offset, 16);

      if (uuid_bytes)
        image_uuid = UUID(uuid_bytes, 16);
      break;
    }

    default:
      break;
    }
    offset = cmd_offset + lc.cmdsize;
  }

  if (!symtab_load_command.cmd)
    return;

  SectionList *section_list = GetSectionList();
  if (section_list == nullptr)
    return;

  const uint32_t addr_byte_size = m_data_nsp->GetAddressByteSize();
  const ByteOrder byte_order = m_data_nsp->GetByteOrder();
  bool bit_width_32 = addr_byte_size == 4;
  const size_t nlist_byte_size =
      bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);

  DataExtractor nlist_data(nullptr, 0, byte_order, addr_byte_size);
  DataExtractor strtab_data(nullptr, 0, byte_order, addr_byte_size);
  DataExtractor function_starts_data(nullptr, 0, byte_order, addr_byte_size);
  DataExtractor indirect_symbol_index_data(nullptr, 0, byte_order,
                                           addr_byte_size);
  DataExtractor dyld_trie_data(nullptr, 0, byte_order, addr_byte_size);

  const addr_t nlist_data_byte_size =
      symtab_load_command.nsyms * nlist_byte_size;
  const addr_t strtab_data_byte_size = symtab_load_command.strsize;
  addr_t strtab_addr = LLDB_INVALID_ADDRESS;

  ProcessSP process_sp(m_process_wp.lock());
  Process *process = process_sp.get();

  uint32_t memory_module_load_level = eMemoryModuleLoadLevelComplete;
  bool is_shared_cache_image = IsSharedCacheBinary();
  bool is_local_shared_cache_image = is_shared_cache_image && !IsInMemory();

  SectionSP text_section_sp(
      section_list->FindSectionByName(GetSegmentNameTEXT()));
  SectionSP data_section_sp(
      section_list->FindSectionByName(GetSegmentNameDATA()));
  SectionSP linkedit_section_sp(
      section_list->FindSectionByName(GetSegmentNameLINKEDIT()));
  SectionSP data_dirty_section_sp(
      section_list->FindSectionByName(GetSegmentNameDATA_DIRTY()));
  SectionSP data_const_section_sp(
      section_list->FindSectionByName(GetSegmentNameDATA_CONST()));
  SectionSP objc_section_sp(
      section_list->FindSectionByName(GetSegmentNameOBJC()));
  SectionSP eh_frame_section_sp;
  SectionSP lldb_no_nlist_section_sp;
  llvm::StringRef g_section_name_eh_frame = GetSectionNameEHFrame();
  llvm::StringRef g_section_name_lldb_no_nlist = GetSectionNameLLDBNoNlist();
  if (text_section_sp.get()) {
    eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName(
        g_section_name_eh_frame);
    lldb_no_nlist_section_sp = text_section_sp->GetChildren().FindSectionByName(
        g_section_name_lldb_no_nlist);
  } else {
    eh_frame_section_sp =
        section_list->FindSectionByName(g_section_name_eh_frame);
    lldb_no_nlist_section_sp =
        section_list->FindSectionByName(g_section_name_lldb_no_nlist);
  }

  if (process && m_header.filetype != llvm::MachO::MH_OBJECT &&
      !is_local_shared_cache_image) {
    Target &target = process->GetTarget();

    memory_module_load_level = target.GetMemoryModuleLoadLevel();

    // If __TEXT,__lldb_no_nlist section is present in this binary,
    // and we're reading it out of memory, do not read any of the
    // nlist entries.  They are not needed in lldb and it may be
    // expensive to load these.  This is to handle a dylib consisting
    // of only metadata, no code, but it has many nlist entries.
    if (lldb_no_nlist_section_sp)
      memory_module_load_level = eMemoryModuleLoadLevelMinimal;

    // Reading mach file from memory in a process or core file...

    if (linkedit_section_sp) {
      addr_t linkedit_load_addr =
          linkedit_section_sp->GetLoadBaseAddress(&target);
      if (linkedit_load_addr == LLDB_INVALID_ADDRESS) {
        // We might be trying to access the symbol table before the
        // __LINKEDIT's load address has been set in the target. We can't
        // fail to read the symbol table, so calculate the right address
        // manually
        linkedit_load_addr = CalculateSectionLoadAddressForMemoryImage(
            m_memory_addr, GetMachHeaderSection(), linkedit_section_sp.get());
      }

      const addr_t linkedit_file_offset = linkedit_section_sp->GetFileOffset();
      const addr_t symoff_addr = linkedit_load_addr +
                                 symtab_load_command.symoff -
                                 linkedit_file_offset;
      strtab_addr = linkedit_load_addr + symtab_load_command.stroff -
                    linkedit_file_offset;

      // Always load dyld - the dynamic linker - from memory if we didn't
      // find a binary anywhere else. lldb will not register
      // dylib/framework/bundle loads/unloads if we don't have the dyld
      // symbols, we force dyld to load from memory despite the user's
      // target.memory-module-load-level setting.
      if (memory_module_load_level == eMemoryModuleLoadLevelComplete ||
          m_header.filetype == llvm::MachO::MH_DYLINKER) {
        DataBufferSP nlist_data_sp(
            ReadMemory(process_sp, symoff_addr, nlist_data_byte_size));
        if (nlist_data_sp)
          nlist_data.SetData(nlist_data_sp, 0, nlist_data_sp->GetByteSize());
        if (dysymtab.nindirectsyms != 0) {
          const addr_t indirect_syms_addr = linkedit_load_addr +
                                            dysymtab.indirectsymoff -
                                            linkedit_file_offset;
          DataBufferSP indirect_syms_data_sp(ReadMemory(
              process_sp, indirect_syms_addr, dysymtab.nindirectsyms * 4));
          if (indirect_syms_data_sp)
            indirect_symbol_index_data.SetData(
                indirect_syms_data_sp, 0, indirect_syms_data_sp->GetByteSize());
          // If this binary is outside the shared cache,
          // cache the string table.
          // Binaries in the shared cache all share a giant string table,
          // and we can't share the string tables across multiple
          // ObjectFileMachO's, so we'd end up re-reading this mega-strtab
          // for every binary in the shared cache - it would be a big perf
          // problem. For binaries outside the shared cache, it's faster to
          // read the entire strtab at once instead of piece-by-piece as we
          // process the nlist records.
          if (!is_shared_cache_image) {
            DataBufferSP strtab_data_sp(
                ReadMemory(process_sp, strtab_addr, strtab_data_byte_size));
            if (strtab_data_sp) {
              strtab_data.SetData(strtab_data_sp, 0,
                                  strtab_data_sp->GetByteSize());
            }
          }
        }
        if (memory_module_load_level >= eMemoryModuleLoadLevelPartial) {
          if (function_starts_load_command.cmd) {
            const addr_t func_start_addr =
                linkedit_load_addr + function_starts_load_command.dataoff -
                linkedit_file_offset;
            DataBufferSP func_start_data_sp(
                ReadMemory(process_sp, func_start_addr,
                           function_starts_load_command.datasize));
            if (func_start_data_sp)
              function_starts_data.SetData(func_start_data_sp, 0,
                                           func_start_data_sp->GetByteSize());
          }
        }
      }
    }
  } else {
    if (is_local_shared_cache_image && linkedit_section_sp) {
      // The load commands in shared cache images are relative to the
      // beginning of the shared cache, not the library image. The
      // data we get handed when creating the ObjectFileMachO starts
      // at the beginning of a specific library and spans to the end
      // of the cache to be able to reach the shared LINKEDIT
      // segments. We need to convert the load command offsets to be
      // relative to the beginning of our specific image.
      lldb::addr_t linkedit_offset = linkedit_section_sp->GetFileOffset();
      lldb::offset_t linkedit_slide =
          linkedit_offset - m_linkedit_original_offset;
      symtab_load_command.symoff += linkedit_slide;
      symtab_load_command.stroff += linkedit_slide;
      dyld_info.export_off += linkedit_slide;
      dysymtab.indirectsymoff += linkedit_slide;
      function_starts_load_command.dataoff += linkedit_slide;
      exports_trie_load_command.dataoff += linkedit_slide;
    }

    nlist_data = *m_data_nsp->GetSubsetExtractorSP(symtab_load_command.symoff,
                                                   nlist_data_byte_size);
    strtab_data = *m_data_nsp->GetSubsetExtractorSP(symtab_load_command.stroff,
                                                    strtab_data_byte_size);

    // We shouldn't have exports data from both the LC_DYLD_INFO command
    // AND the LC_DYLD_EXPORTS_TRIE command in the same binary:
    lldbassert(!((dyld_info.export_size > 0)
                 && (exports_trie_load_command.datasize > 0)));
    if (dyld_info.export_size > 0) {
      dyld_trie_data = *m_data_nsp->GetSubsetExtractorSP(dyld_info.export_off,
                                                         dyld_info.export_size);
    } else if (exports_trie_load_command.datasize > 0) {
      dyld_trie_data =
          *m_data_nsp->GetSubsetExtractorSP(exports_trie_load_command.dataoff,
                                            exports_trie_load_command.datasize);
    }

    if (dysymtab.nindirectsyms != 0) {
      indirect_symbol_index_data = *m_data_nsp->GetSubsetExtractorSP(
          dysymtab.indirectsymoff, dysymtab.nindirectsyms * 4);
    }
    if (function_starts_load_command.cmd) {
      function_starts_data = *m_data_nsp->GetSubsetExtractorSP(
          function_starts_load_command.dataoff,
          function_starts_load_command.datasize);
    }
  }

  const bool have_strtab_data = strtab_data.GetByteSize() > 0;

  const bool is_arm = (m_header.cputype == llvm::MachO::CPU_TYPE_ARM);
  const bool always_thumb = GetArchitecture().IsAlwaysThumbInstructions();

  // lldb works best if it knows the start address of all functions in a
  // module. Linker symbols or debug info are normally the best source of
  // information for start addr / size but they may be stripped in a released
  // binary. Two additional sources of information exist in Mach-O binaries:
  //    LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each
  //    function's start address in the
  //                         binary, relative to the text section.
  //    eh_frame           - the eh_frame FDEs have the start addr & size of
  //    each function
  //  LC_FUNCTION_STARTS is the fastest source to read in, and is present on
  //  all modern binaries.
  //  Binaries built to run on older releases may need to use eh_frame
  //  information.

  if (text_section_sp && function_starts_data.GetByteSize()) {
    FunctionStarts::Entry function_start_entry;
    function_start_entry.data = false;
    lldb::offset_t function_start_offset = 0;
    function_start_entry.addr = text_section_sp->GetFileAddress();
    uint64_t delta;
    while ((delta = function_starts_data.GetULEB128(&function_start_offset)) >
           0) {
      // Now append the current entry
      function_start_entry.addr += delta;
      if (is_arm) {
        if (function_start_entry.addr & 1) {
          function_start_entry.addr &= THUMB_ADDRESS_BIT_MASK;
          function_start_entry.data = true;
        } else if (always_thumb) {
          function_start_entry.data = true;
        }
      }
      function_starts.Append(function_start_entry);
    }
  } else {
    // If m_type is eTypeDebugInfo, then this is a dSYM - it will have the
    // load command claiming an eh_frame but it doesn't actually have the
    // eh_frame content.  And if we have a dSYM, we don't need to do any of
    // this fill-in-the-missing-symbols works anyway - the debug info should
    // give us all the functions in the module.
    if (text_section_sp.get() && eh_frame_section_sp.get() &&
        m_type != eTypeDebugInfo) {
      DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp,
                                  DWARFCallFrameInfo::EH);
      DWARFCallFrameInfo::FunctionAddressAndSizeVector functions;
      eh_frame.GetFunctionAddressAndSizeVector(functions);
      addr_t text_base_addr = text_section_sp->GetFileAddress();
      size_t count = functions.GetSize();
      for (size_t i = 0; i < count; ++i) {
        const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func =
            functions.GetEntryAtIndex(i);
        if (func) {
          FunctionStarts::Entry function_start_entry;
          function_start_entry.addr = func->base - text_base_addr;
          if (is_arm) {
            if (function_start_entry.addr & 1) {
              function_start_entry.addr &= THUMB_ADDRESS_BIT_MASK;
              function_start_entry.data = true;
            } else if (always_thumb) {
              function_start_entry.data = true;
            }
          }
          function_starts.Append(function_start_entry);
        }
      }
    }
  }

  const size_t function_starts_count = function_starts.GetSize();

  // For user process binaries (executables, dylibs, frameworks, bundles), if
  // we don't have LC_FUNCTION_STARTS/eh_frame section in this binary, we're
  // going to assume the binary has been stripped.  Don't allow assembly
  // language instruction emulation because we don't know proper function
  // start boundaries.
  //
  // For all other types of binaries (kernels, stand-alone bare board
  // binaries, kexts), they may not have LC_FUNCTION_STARTS / eh_frame
  // sections - we should not make any assumptions about them based on that.
  if (function_starts_count == 0 && CalculateStrata() == eStrataUser) {
    m_allow_assembly_emulation_unwind_plans = false;
    Log *unwind_or_symbol_log(GetLog(LLDBLog::Symbols | LLDBLog::Unwind));

    if (unwind_or_symbol_log)
      module_sp->LogMessage(
          unwind_or_symbol_log,
          "no LC_FUNCTION_STARTS, will not allow assembly profiled unwinds");
  }

  const user_id_t TEXT_eh_frame_sectID = eh_frame_section_sp.get()
                                             ? eh_frame_section_sp->GetID()
                                             : static_cast<user_id_t>(NO_SECT);

  uint32_t N_SO_index = UINT32_MAX;

  MachSymtabSectionInfo section_info(section_list);
  std::vector<uint32_t> N_FUN_indexes;
  std::vector<uint32_t> N_NSYM_indexes;
  std::vector<uint32_t> N_INCL_indexes;
  std::vector<uint32_t> N_BRAC_indexes;
  std::vector<uint32_t> N_COMM_indexes;
  typedef std::multimap<uint64_t, uint32_t> ValueToSymbolIndexMap;
  typedef llvm::DenseMap<uint32_t, uint32_t> NListIndexToSymbolIndexMap;
  typedef llvm::DenseMap<const char *, uint32_t> ConstNameToSymbolIndexMap;
  ValueToSymbolIndexMap N_FUN_addr_to_sym_idx;
  ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx;
  ConstNameToSymbolIndexMap N_GSYM_name_to_sym_idx;
  // Any symbols that get merged into another will get an entry in this map
  // so we know
  NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx;
  uint32_t nlist_idx = 0;
  Symbol *symbol_ptr = nullptr;

  uint32_t sym_idx = 0;
  Symbol *sym = nullptr;
  size_t num_syms = 0;
  std::string memory_symbol_name;
  uint32_t unmapped_local_symbols_found = 0;

  std::vector<TrieEntryWithOffset> reexport_trie_entries;
  std::vector<TrieEntryWithOffset> external_sym_trie_entries;
  std::set<lldb::addr_t> resolver_addresses;

  const size_t dyld_trie_data_size = dyld_trie_data.GetByteSize();
  if (dyld_trie_data_size > 0) {
    LLDB_LOG(log, "Parsing {0} bytes of dyld trie data", dyld_trie_data_size);
    SectionSP text_segment_sp =
        GetSectionList()->FindSectionByName(GetSegmentNameTEXT());
    lldb::addr_t text_segment_file_addr = LLDB_INVALID_ADDRESS;
    if (text_segment_sp)
      text_segment_file_addr = text_segment_sp->GetFileAddress();
    ParseTrieEntries(dyld_trie_data, is_arm, text_segment_file_addr,
                     resolver_addresses, reexport_trie_entries,
                     external_sym_trie_entries);
  }

  typedef std::set<ConstString> IndirectSymbols;
  IndirectSymbols indirect_symbol_names;

#if TARGET_OS_IPHONE

  // Some recent builds of the dyld_shared_cache (hereafter: DSC) have been
  // optimized by moving LOCAL symbols out of the memory mapped portion of
  // the DSC. The symbol information has all been retained, but it isn't
  // available in the normal nlist data. However, there *are* duplicate
  // entries of *some*
  // LOCAL symbols in the normal nlist data. To handle this situation
  // correctly, we must first attempt
  // to parse any DSC unmapped symbol information. If we find any, we set a
  // flag that tells the normal nlist parser to ignore all LOCAL symbols.

  if (IsSharedCacheBinary()) {
    // Before we can start mapping the DSC, we need to make certain the
    // target process is actually using the cache we can find.

    // Next we need to determine the correct path for the dyld shared cache.

    ArchSpec header_arch = GetArchitecture();

    UUID dsc_uuid;
    UUID process_shared_cache_uuid;
    addr_t process_shared_cache_base_addr;

    if (process) {
      GetProcessSharedCacheUUID(process, process_shared_cache_base_addr,
                                process_shared_cache_uuid);
    }

    __block bool found_image = false;
    __block void *nlist_buffer = nullptr;
    __block unsigned nlist_count = 0;
    __block char *string_table = nullptr;
    __block vm_offset_t vm_nlist_memory = 0;
    __block mach_msg_type_number_t vm_nlist_bytes_read = 0;
    __block vm_offset_t vm_string_memory = 0;
    __block mach_msg_type_number_t vm_string_bytes_read = 0;

    llvm::scope_exit _(^{
      if (vm_nlist_memory)
        vm_deallocate(mach_task_self(), vm_nlist_memory, vm_nlist_bytes_read);
      if (vm_string_memory)
        vm_deallocate(mach_task_self(), vm_string_memory, vm_string_bytes_read);
    });

    typedef llvm::DenseMap<ConstString, uint16_t> UndefinedNameToDescMap;
    typedef llvm::DenseMap<uint32_t, ConstString> SymbolIndexToName;
    UndefinedNameToDescMap undefined_name_to_desc;
    SymbolIndexToName reexport_shlib_needs_fixup;

    dyld_for_each_installed_shared_cache(^(dyld_shared_cache_t shared_cache) {
      uuid_t cache_uuid;
      dyld_shared_cache_copy_uuid(shared_cache, &cache_uuid);
      if (found_image)
        return;

        if (process_shared_cache_uuid.IsValid() &&
          process_shared_cache_uuid != UUID(&cache_uuid, 16))
        return;

      dyld_shared_cache_for_each_image(shared_cache, ^(dyld_image_t image) {
        uuid_t dsc_image_uuid;
        if (found_image)
          return;

        dyld_image_copy_uuid(image, &dsc_image_uuid);
        if (image_uuid != UUID(dsc_image_uuid, 16))
          return;

        found_image = true;

        // Compute the size of the string table. We need to ask dyld for a
        // new SPI to avoid this step.
        dyld_image_local_nlist_content_4Symbolication(
            image, ^(const void *nlistStart, uint64_t nlistCount,
                     const char *stringTable) {
              if (!nlistStart || !nlistCount)
                return;

              // The buffers passed here are valid only inside the block.
              // Use vm_read to make a cheap copy of them available for our
              // processing later.
              kern_return_t ret =
                  vm_read(mach_task_self(), (vm_address_t)nlistStart,
                          nlist_byte_size * nlistCount, &vm_nlist_memory,
                          &vm_nlist_bytes_read);
              if (ret != KERN_SUCCESS)
                return;
              assert(vm_nlist_bytes_read == nlist_byte_size * nlistCount);

              // We don't know the size of the string table. It's cheaper
              // to map the whole VM region than to determine the size by
              // parsing all the nlist entries.
              vm_address_t string_address = (vm_address_t)stringTable;
              vm_size_t region_size;
              mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
              vm_region_basic_info_data_t info;
              memory_object_name_t object;
              ret = vm_region_64(mach_task_self(), &string_address,
                                 &region_size, VM_REGION_BASIC_INFO_64,
                                 (vm_region_info_t)&info, &info_count, &object);
              if (ret != KERN_SUCCESS)
                return;

              ret = vm_read(mach_task_self(), (vm_address_t)stringTable,
                            region_size -
                                ((vm_address_t)stringTable - string_address),
                            &vm_string_memory, &vm_string_bytes_read);
              if (ret != KERN_SUCCESS)
                return;

              nlist_buffer = (void *)vm_nlist_memory;
              string_table = (char *)vm_string_memory;
              nlist_count = nlistCount;
            });
      });
    });
    if (nlist_buffer) {
      DataExtractor dsc_local_symbols_data(nlist_buffer,
                                           nlist_count * nlist_byte_size,
                                           byte_order, addr_byte_size);
      DataExtractor dsc_string_table_data(string_table, vm_string_bytes_read,
                                          byte_order, addr_byte_size);
      unmapped_local_symbols_found = nlist_count;

                // The normal nlist code cannot correctly size the Symbols
                // array, we need to allocate it here.
                sym = symtab.Resize(
                    symtab_load_command.nsyms + m_dysymtab.nindirectsyms +
                    unmapped_local_symbols_found - m_dysymtab.nlocalsym);
                num_syms = symtab.GetNumSymbols();

      lldb::offset_t nlist_data_offset = 0;

                for (uint32_t nlist_index = 0;
                     nlist_index < nlist_count;
                     nlist_index++) {
                  /////////////////////////////
                  {
                    std::optional<struct nlist_64> nlist_maybe =
                        ParseNList(dsc_local_symbols_data, nlist_data_offset,
                                   nlist_byte_size);
                    if (!nlist_maybe)
                      break;
                    struct nlist_64 nlist = *nlist_maybe;

                    SymbolType type = eSymbolTypeInvalid;
                    const char *symbol_name = NULL;
                    std::optional<llvm::StringRef> name =
                        dsc_string_table_data.PeekCStr(nlist.n_strx);

                    if (!name) {
                      // No symbol should be NULL, even the symbols with no
                      // string values should have an offset zero which
                      // points to an empty C-string
                      Debugger::ReportError(llvm::formatv(
                          "DSC unmapped local symbol[{0}] has invalid or "
                          "unterminated string table offset {1:x} in {2}, "
                          "ignoring symbol",
                          nlist_index, nlist.n_strx,
                          module_sp->GetFileSpec().GetPath()));
                      continue;
                    }
                    // The code below spells "no name" as a NULL pointer.
                    if (!name->empty())
                      symbol_name = name->data();

                    const char *symbol_name_non_abi_mangled = NULL;

                    SectionSP symbol_section;
                    bool add_nlist = true;
                    bool is_debug = ((nlist.n_type & N_STAB) != 0);
                    bool demangled_is_synthesized = false;
                    bool is_gsym = false;
                    bool set_value = true;

                    assert(sym_idx < num_syms);

                    sym[sym_idx].SetDebug(is_debug);

                    if (is_debug) {
                      switch (nlist.n_type) {
                      case N_GSYM:
                        // global symbol: name,,NO_SECT,type,0
                        // Sometimes the N_GSYM value contains the address.

                        // FIXME: In the .o files, we have a GSYM and a debug
                        // symbol for all the ObjC data.  They
                        // have the same address, but we want to ensure that
                        // we always find only the real symbol, 'cause we
                        // don't currently correctly attribute the
                        // GSYM one to the ObjCClass/Ivar/MetaClass
                        // symbol type.  This is a temporary hack to make
                        // sure the ObjectiveC symbols get treated correctly.
                        // To do this right, we should coalesce all the GSYM
                        // & global symbols that have the same address.

                        is_gsym = true;
                        sym[sym_idx].SetExternal(true);

                        if (TryParseV2ObjCMetadataSymbol(
                                symbol_name, symbol_name_non_abi_mangled,
                                type)) {
                          demangled_is_synthesized = true;
                        } else {
                          if (nlist.n_value != 0)
                            symbol_section = section_info.GetSection(
                                nlist.n_sect, nlist.n_value);

                          type = eSymbolTypeData;
                        }
                        break;

                      case N_FNAME:
                        // procedure name (f77 kludge): name,,NO_SECT,0,0
                        type = eSymbolTypeCompiler;
                        break;

                      case N_FUN:
                        // procedure: name,,n_sect,linenumber,address
                        if (symbol_name) {
                          type = eSymbolTypeCode;
                          symbol_section = section_info.GetSection(
                              nlist.n_sect, nlist.n_value);

                          N_FUN_addr_to_sym_idx.insert(
                              std::make_pair(nlist.n_value, sym_idx));
                          // We use the current number of symbols in the
                          // symbol table in lieu of using nlist_idx in case
                          // we ever start trimming entries out
                          N_FUN_indexes.push_back(sym_idx);
                        } else {
                          type = eSymbolTypeCompiler;

                          if (!N_FUN_indexes.empty()) {
                            // Copy the size of the function into the
                            // original
                            // STAB entry so we don't have
                            // to hunt for it later
                            symtab.SymbolAtIndex(N_FUN_indexes.back())
                                ->SetByteSize(nlist.n_value);
                            N_FUN_indexes.pop_back();
                            // We don't really need the end function STAB as
                            // it contains the size which we already placed
                            // with the original symbol, so don't add it if
                            // we want a minimal symbol table
                            add_nlist = false;
                          }
                        }
                        break;

                      case N_STSYM:
                        // static symbol: name,,n_sect,type,address
                        N_STSYM_addr_to_sym_idx.insert(
                            std::make_pair(nlist.n_value, sym_idx));
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        if (symbol_name && symbol_name[0]) {
                          type = ObjectFile::GetSymbolTypeFromName(
                              symbol_name + 1, eSymbolTypeData);
                        }
                        break;

                      case N_LCSYM:
                        // .lcomm symbol: name,,n_sect,type,address
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        type = eSymbolTypeCommonBlock;
                        break;

                      case N_BNSYM:
                        // We use the current number of symbols in the symbol
                        // table in lieu of using nlist_idx in case we ever
                        // start trimming entries out Skip these if we want
                        // minimal symbol tables
                        add_nlist = false;
                        break;

                      case N_ENSYM:
                        // Set the size of the N_BNSYM to the terminating
                        // index of this N_ENSYM so that we can always skip
                        // the entire symbol if we need to navigate more
                        // quickly at the source level when parsing STABS
                        // Skip these if we want minimal symbol tables
                        add_nlist = false;
                        break;

                      case N_OPT:
                        // emitted with gcc2_compiled and in gcc source
                        type = eSymbolTypeCompiler;
                        break;

                      case N_RSYM:
                        // register sym: name,,NO_SECT,type,register
                        type = eSymbolTypeVariable;
                        break;

                      case N_SLINE:
                        // src line: 0,,n_sect,linenumber,address
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        type = eSymbolTypeLineEntry;
                        break;

                      case N_SSYM:
                        // structure elt: name,,NO_SECT,type,struct_offset
                        type = eSymbolTypeVariableType;
                        break;

                      case N_SO:
                        // source file name
                        type = eSymbolTypeSourceFile;
                        if (symbol_name == NULL) {
                          add_nlist = false;
                          if (N_SO_index != UINT32_MAX) {
                            // Set the size of the N_SO to the terminating
                            // index of this N_SO so that we can always skip
                            // the entire N_SO if we need to navigate more
                            // quickly at the source level when parsing STABS
                            symbol_ptr = symtab.SymbolAtIndex(N_SO_index);
                            symbol_ptr->SetByteSize(sym_idx);
                            symbol_ptr->SetSizeIsSibling(true);
                          }
                          N_NSYM_indexes.clear();
                          N_INCL_indexes.clear();
                          N_BRAC_indexes.clear();
                          N_COMM_indexes.clear();
                          N_FUN_indexes.clear();
                          N_SO_index = UINT32_MAX;
                        } else {
                          // We use the current number of symbols in the
                          // symbol table in lieu of using nlist_idx in case
                          // we ever start trimming entries out
                          const bool N_SO_has_full_path = symbol_name[0] == '/';
                          if (N_SO_has_full_path) {
                            if ((N_SO_index == sym_idx - 1) &&
                                ((sym_idx - 1) < num_syms)) {
                              // We have two consecutive N_SO entries where
                              // the first contains a directory and the
                              // second contains a full path.
                              sym[sym_idx - 1].GetMangled().SetValue(
                                  ConstString(symbol_name));
                              m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
                              add_nlist = false;
                            } else {
                              // This is the first entry in a N_SO that
                              // contains a directory or
                              // a full path to the source file
                              N_SO_index = sym_idx;
                            }
                          } else if ((N_SO_index == sym_idx - 1) &&
                                     ((sym_idx - 1) < num_syms)) {
                            // This is usually the second N_SO entry that
                            // contains just the filename, so here we combine
                            // it with the first one if we are minimizing the
                            // symbol table
                            const char *so_path = sym[sym_idx - 1]
                                                      .GetMangled()
                                                      .GetDemangledName()
                                                      .AsCString();
                            if (so_path && so_path[0]) {
                              std::string full_so_path(so_path);
                              const size_t double_slash_pos =
                                  full_so_path.find("//");
                              if (double_slash_pos != std::string::npos) {
                                // The linker has been generating bad N_SO
                                // entries with doubled up paths
                                // in the format "%s%s" where the first
                                // string in the DW_AT_comp_dir, and the
                                // second is the directory for the source
                                // file so you end up with a path that looks
                                // like "/tmp/src//tmp/src/"
                                FileSpec so_dir(so_path);
                                if (!FileSystem::Instance().Exists(so_dir)) {
                                  so_dir.SetFile(
                                      &full_so_path[double_slash_pos + 1],
                                      FileSpec::Style::native);
                                  if (FileSystem::Instance().Exists(so_dir)) {
                                    // Trim off the incorrect path
                                    full_so_path.erase(0, double_slash_pos + 1);
                                  }
                                }
                              }
                              if (*full_so_path.rbegin() != '/')
                                full_so_path += '/';
                              full_so_path += symbol_name;
                              sym[sym_idx - 1].GetMangled().SetValue(
                                  ConstString(full_so_path.c_str()));
                              add_nlist = false;
                              m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
                            }
                          } else {
                            // This could be a relative path to a N_SO
                            N_SO_index = sym_idx;
                          }
                        }
                        break;

                      case N_OSO:
                        // object file name: name,,0,0,st_mtime
                        type = eSymbolTypeObjectFile;
                        break;

                      case N_LSYM:
                        // local sym: name,,NO_SECT,type,offset
                        type = eSymbolTypeLocal;
                        break;

                      // INCL scopes
                      case N_BINCL:
                        // include file beginning: name,,NO_SECT,0,sum We use
                        // the current number of symbols in the symbol table
                        // in lieu of using nlist_idx in case we ever start
                        // trimming entries out
                        N_INCL_indexes.push_back(sym_idx);
                        type = eSymbolTypeScopeBegin;
                        break;

                      case N_EINCL:
                        // include file end: name,,NO_SECT,0,0
                        // Set the size of the N_BINCL to the terminating
                        // index of this N_EINCL so that we can always skip
                        // the entire symbol if we need to navigate more
                        // quickly at the source level when parsing STABS
                        if (!N_INCL_indexes.empty()) {
                          symbol_ptr =
                              symtab.SymbolAtIndex(N_INCL_indexes.back());
                          symbol_ptr->SetByteSize(sym_idx + 1);
                          symbol_ptr->SetSizeIsSibling(true);
                          N_INCL_indexes.pop_back();
                        }
                        type = eSymbolTypeScopeEnd;
                        break;

                      case N_SOL:
                        // #included file name: name,,n_sect,0,address
                        type = eSymbolTypeHeaderFile;

                        // We currently don't use the header files on darwin
                        add_nlist = false;
                        break;

                      case N_PARAMS:
                        // compiler parameters: name,,NO_SECT,0,0
                        type = eSymbolTypeCompiler;
                        break;

                      case N_VERSION:
                        // compiler version: name,,NO_SECT,0,0
                        type = eSymbolTypeCompiler;
                        break;

                      case N_OLEVEL:
                        // compiler -O level: name,,NO_SECT,0,0
                        type = eSymbolTypeCompiler;
                        break;

                      case N_PSYM:
                        // parameter: name,,NO_SECT,type,offset
                        type = eSymbolTypeVariable;
                        break;

                      case N_ENTRY:
                        // alternate entry: name,,n_sect,linenumber,address
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        type = eSymbolTypeLineEntry;
                        break;

                      // Left and Right Braces
                      case N_LBRAC:
                        // left bracket: 0,,NO_SECT,nesting level,address We
                        // use the current number of symbols in the symbol
                        // table in lieu of using nlist_idx in case we ever
                        // start trimming entries out
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        N_BRAC_indexes.push_back(sym_idx);
                        type = eSymbolTypeScopeBegin;
                        break;

                      case N_RBRAC:
                        // right bracket: 0,,NO_SECT,nesting level,address
                        // Set the size of the N_LBRAC to the terminating
                        // index of this N_RBRAC so that we can always skip
                        // the entire symbol if we need to navigate more
                        // quickly at the source level when parsing STABS
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        if (!N_BRAC_indexes.empty()) {
                          symbol_ptr =
                              symtab.SymbolAtIndex(N_BRAC_indexes.back());
                          symbol_ptr->SetByteSize(sym_idx + 1);
                          symbol_ptr->SetSizeIsSibling(true);
                          N_BRAC_indexes.pop_back();
                        }
                        type = eSymbolTypeScopeEnd;
                        break;

                      case N_EXCL:
                        // deleted include file: name,,NO_SECT,0,sum
                        type = eSymbolTypeHeaderFile;
                        break;

                      // COMM scopes
                      case N_BCOMM:
                        // begin common: name,,NO_SECT,0,0
                        // We use the current number of symbols in the symbol
                        // table in lieu of using nlist_idx in case we ever
                        // start trimming entries out
                        type = eSymbolTypeScopeBegin;
                        N_COMM_indexes.push_back(sym_idx);
                        break;

                      case N_ECOML:
                        // end common (local name): 0,,n_sect,0,address
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);
                        // Fall through

                      case N_ECOMM:
                        // end common: name,,n_sect,0,0
                        // Set the size of the N_BCOMM to the terminating
                        // index of this N_ECOMM/N_ECOML so that we can
                        // always skip the entire symbol if we need to
                        // navigate more quickly at the source level when
                        // parsing STABS
                        if (!N_COMM_indexes.empty()) {
                          symbol_ptr =
                              symtab.SymbolAtIndex(N_COMM_indexes.back());
                          symbol_ptr->SetByteSize(sym_idx + 1);
                          symbol_ptr->SetSizeIsSibling(true);
                          N_COMM_indexes.pop_back();
                        }
                        type = eSymbolTypeScopeEnd;
                        break;

                      case N_LENG:
                        // second stab entry with length information
                        type = eSymbolTypeAdditional;
                        break;

                      default:
                        break;
                      }
                    } else {
                      // uint8_t n_pext    = N_PEXT & nlist.n_type;
                      uint8_t n_type = N_TYPE & nlist.n_type;
                      sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0);

                      switch (n_type) {
                      case N_INDR: {
                        std::optional<llvm::StringRef> reexport_name_str =
                            strtab_data.PeekCStr(nlist.n_value);
                        if (reexport_name_str && !reexport_name_str->empty()) {
                          type = eSymbolTypeReExported;
                          ConstString reexport_name(
                              reexport_name_str->drop_front(
                                  reexport_name_str->front() == '_' ? 1 : 0));
                          sym[sym_idx].SetReExportedSymbolName(reexport_name);
                          set_value = false;
                          reexport_shlib_needs_fixup[sym_idx] = reexport_name;
                          indirect_symbol_names.insert(ConstString(
                              symbol_name + ((symbol_name[0] == '_') ? 1 : 0)));
                        } else
                          type = eSymbolTypeUndefined;
                      } break;

                      case N_UNDF:
                        if (symbol_name && symbol_name[0]) {
                          ConstString undefined_name(
                              symbol_name + ((symbol_name[0] == '_') ? 1 : 0));
                          undefined_name_to_desc[undefined_name] = nlist.n_desc;
                        }
                      // Fall through
                      case N_PBUD:
                        type = eSymbolTypeUndefined;
                        break;

                      case N_ABS:
                        type = eSymbolTypeAbsolute;
                        break;

                      case N_SECT: {
                        symbol_section = section_info.GetSection(nlist.n_sect,
                                                                 nlist.n_value);

                        if (symbol_section == NULL) {
                          // TODO: warn about this?
                          add_nlist = false;
                          break;
                        }

                        if (TEXT_eh_frame_sectID == nlist.n_sect) {
                          type = eSymbolTypeException;
                        } else {
                          uint32_t section_type =
                              symbol_section->Get() & SECTION_TYPE;

                          switch (section_type) {
                          case S_CSTRING_LITERALS:
                            type = eSymbolTypeData;
                            break; // section with only literal C strings
                          case S_4BYTE_LITERALS:
                            type = eSymbolTypeData;
                            break; // section with only 4 byte literals
                          case S_8BYTE_LITERALS:
                            type = eSymbolTypeData;
                            break; // section with only 8 byte literals
                          case S_LITERAL_POINTERS:
                            type = eSymbolTypeTrampoline;
                            break; // section with only pointers to literals
                          case S_NON_LAZY_SYMBOL_POINTERS:
                            type = eSymbolTypeTrampoline;
                            break; // section with only non-lazy symbol
                                   // pointers
                          case S_LAZY_SYMBOL_POINTERS:
                            type = eSymbolTypeTrampoline;
                            break; // section with only lazy symbol pointers
                          case S_SYMBOL_STUBS:
                            type = eSymbolTypeTrampoline;
                            break; // section with only symbol stubs, byte
                                   // size of stub in the reserved2 field
                          case S_MOD_INIT_FUNC_POINTERS:
                            type = eSymbolTypeCode;
                            break; // section with only function pointers for
                                   // initialization
                          case S_MOD_TERM_FUNC_POINTERS:
                            type = eSymbolTypeCode;
                            break; // section with only function pointers for
                                   // termination
                          case S_INTERPOSING:
                            type = eSymbolTypeTrampoline;
                            break; // section with only pairs of function
                                   // pointers for interposing
                          case S_16BYTE_LITERALS:
                            type = eSymbolTypeData;
                            break; // section with only 16 byte literals
                          case S_DTRACE_DOF:
                            type = eSymbolTypeInstrumentation;
                            break;
                          case S_LAZY_DYLIB_SYMBOL_POINTERS:
                            type = eSymbolTypeTrampoline;
                            break;
                          default:
                            switch (symbol_section->GetType()) {
                            case lldb::eSectionTypeCode:
                              type = eSymbolTypeCode;
                              break;
                            case eSectionTypeData:
                            case eSectionTypeDataCString: // Inlined C string
                                                          // data
                            case eSectionTypeDataCStringPointers: // Pointers
                                                                  // to C
                                                                  // string
                                                                  // data
                            case eSectionTypeDataSymbolAddress:   // Address of
                                                                  // a symbol in
                                                                  // the symbol
                                                                  // table
                            case eSectionTypeData4:
                            case eSectionTypeData8:
                            case eSectionTypeData16:
                              type = eSymbolTypeData;
                              break;
                            default:
                              break;
                            }
                            break;
                          }

                          if (type == eSymbolTypeInvalid) {
                            llvm::StringRef symbol_sect_name =
                                symbol_section->GetName();
                            if (symbol_section->IsDescendant(
                                    text_section_sp.get())) {
                              if (symbol_section->IsClear(
                                      S_ATTR_PURE_INSTRUCTIONS |
                                      S_ATTR_SELF_MODIFYING_CODE |
                                      S_ATTR_SOME_INSTRUCTIONS))
                                type = eSymbolTypeData;
                              else
                                type = eSymbolTypeCode;
                            } else if (symbol_section->IsDescendant(
                                           data_section_sp.get()) ||
                                       symbol_section->IsDescendant(
                                           data_dirty_section_sp.get()) ||
                                       symbol_section->IsDescendant(
                                           data_const_section_sp.get())) {
                              if (symbol_sect_name.starts_with("__objc")) {
                                type = eSymbolTypeRuntime;

                                if (TryParseV2ObjCMetadataSymbol(
                                        symbol_name,
                                        symbol_name_non_abi_mangled, type))
                                  demangled_is_synthesized = true;
                              } else if (symbol_sect_name.starts_with("__gcc_except_tab")) {
                                type = eSymbolTypeException;
                              } else {
                                type = eSymbolTypeData;
                              }
                            } else if (symbol_sect_name.starts_with("__IMPORT")) 
                              type = eSymbolTypeTrampoline;
                            } else if (symbol_section->IsDescendant(
                                           objc_section_sp.get())) {
                              type = eSymbolTypeRuntime;
                              if (symbol_name && symbol_name[0] == '.') {
                                llvm::StringRef symbol_name_ref(symbol_name);
                                llvm::StringRef
                                    g_objc_v1_prefix_class(".objc_class_name_");
                                if (symbol_name_ref.starts_with(
                                        g_objc_v1_prefix_class)) {
                                  symbol_name_non_abi_mangled = symbol_name;
                                  symbol_name = symbol_name +
                                                g_objc_v1_prefix_class.size();
                                  type = eSymbolTypeObjCClass;
                                  demangled_is_synthesized = true;
                                }
                              }
                            }
                          }
                        }
                      } break;
                      }
                    }

                    if (add_nlist) {
                      uint64_t symbol_value = nlist.n_value;
                      if (symbol_name_non_abi_mangled) {
                        sym[sym_idx].GetMangled().SetMangledName(
                            ConstString(symbol_name_non_abi_mangled));
                        sym[sym_idx].GetMangled().SetDemangledName(
                            ConstString(symbol_name));
                      } else {
                        if (symbol_name && symbol_name[0] == '_') {
                          symbol_name++; // Skip the leading underscore
                        }

                        if (symbol_name) {
                          ConstString const_symbol_name(symbol_name);
                          sym[sym_idx].GetMangled().SetValue(const_symbol_name);
                          if (is_gsym && is_debug) {
                            const char *gsym_name =
                                sym[sym_idx]
                                    .GetMangled()
                                    .GetName(Mangled::ePreferMangled)
                                    .GetCString();
                            if (gsym_name)
                              N_GSYM_name_to_sym_idx[gsym_name] = sym_idx;
                          }
                        }
                      }
                      if (symbol_section) {
                        const addr_t section_file_addr =
                            symbol_section->GetFileAddress();
                        symbol_value -= section_file_addr;
                      }

                      if (is_debug == false) {
                        if (type == eSymbolTypeCode) {
                          // See if we can find a N_FUN entry for any code
                          // symbols. If we do find a match, and the name
                          // matches, then we can merge the two into just the
                          // function symbol to avoid duplicate entries in
                          // the symbol table
                          auto range =
                              N_FUN_addr_to_sym_idx.equal_range(nlist.n_value);
                          if (range.first != range.second) {
                            bool found_it = false;
                            for (auto pos = range.first; pos != range.second;
                                 ++pos) {
                              if (sym[sym_idx].GetMangled().GetName(
                                      Mangled::ePreferMangled) ==
                                  sym[pos->second].GetMangled().GetName(
                                      Mangled::ePreferMangled)) {
                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
                                // We just need the flags from the linker
                                // symbol, so put these flags
                                // into the N_FUN flags to avoid duplicate
                                // symbols in the symbol table
                                sym[pos->second].SetExternal(
                                    sym[sym_idx].IsExternal());
                                sym[pos->second].SetFlags(nlist.n_type << 16 |
                                                          nlist.n_desc);
                                if (resolver_addresses.find(nlist.n_value) !=
                                    resolver_addresses.end())
                                  sym[pos->second].SetType(eSymbolTypeResolver);
                                sym[sym_idx].Clear();
                                found_it = true;
                                break;
                              }
                            }
                            if (found_it)
                              continue;
                          } else {
                            if (resolver_addresses.find(nlist.n_value) !=
                                resolver_addresses.end())
                              type = eSymbolTypeResolver;
                          }
                        } else if (type == eSymbolTypeData ||
                                   type == eSymbolTypeObjCClass ||
                                   type == eSymbolTypeObjCMetaClass ||
                                   type == eSymbolTypeObjCIVar) {
                          // See if we can find a N_STSYM entry for any data
                          // symbols. If we do find a match, and the name
                          // matches, then we can merge the two into just the
                          // Static symbol to avoid duplicate entries in the
                          // symbol table
                          auto range = N_STSYM_addr_to_sym_idx.equal_range(
                              nlist.n_value);
                          if (range.first != range.second) {
                            bool found_it = false;
                            for (auto pos = range.first; pos != range.second;
                                 ++pos) {
                              if (sym[sym_idx].GetMangled().GetName(
                                      Mangled::ePreferMangled) ==
                                  sym[pos->second].GetMangled().GetName(
                                      Mangled::ePreferMangled)) {
                                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
                                // We just need the flags from the linker
                                // symbol, so put these flags
                                // into the N_STSYM flags to avoid duplicate
                                // symbols in the symbol table
                                sym[pos->second].SetExternal(
                                    sym[sym_idx].IsExternal());
                                sym[pos->second].SetFlags(nlist.n_type << 16 |
                                                          nlist.n_desc);
                                sym[sym_idx].Clear();
                                found_it = true;
                                break;
                              }
                            }
                            if (found_it)
                              continue;
                          } else {
                            const char *gsym_name =
                                sym[sym_idx]
                                    .GetMangled()
                                    .GetName(Mangled::ePreferMangled)
                                    .GetCString();
                            if (gsym_name) {
                              // Combine N_GSYM stab entries with the non
                              // stab symbol
                              ConstNameToSymbolIndexMap::const_iterator pos =
                                  N_GSYM_name_to_sym_idx.find(gsym_name);
                              if (pos != N_GSYM_name_to_sym_idx.end()) {
                                const uint32_t GSYM_sym_idx = pos->second;
                                m_nlist_idx_to_sym_idx[nlist_idx] =
                                    GSYM_sym_idx;
                                // Copy the address, because often the N_GSYM
                                // address has an invalid address of zero
                                // when the global is a common symbol
                                sym[GSYM_sym_idx].GetAddressRef() =
                                    Address(symbol_section, symbol_value);
                                add_symbol_addr(sym[GSYM_sym_idx]
                                                    .GetAddress()
                                                    .GetFileAddress());
                                // We just need the flags from the linker
                                // symbol, so put these flags
                                // into the N_GSYM flags to avoid duplicate
                                // symbols in the symbol table
                                sym[GSYM_sym_idx].SetFlags(nlist.n_type << 16 |
                                                           nlist.n_desc);
                                sym[sym_idx].Clear();
                                continue;
                              }
                            }
                          }
                        }
                      }

                      sym[sym_idx].SetID(nlist_idx);
                      sym[sym_idx].SetType(type);
                      if (set_value) {
                        sym[sym_idx].GetAddressRef() =
                            Address(symbol_section, symbol_value);
                        add_symbol_addr(
                            sym[sym_idx].GetAddress().GetFileAddress());
                      }
                      sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);

                      if (demangled_is_synthesized)
                        sym[sym_idx].SetDemangledNameIsSynthesized(true);
                      ++sym_idx;
                    } else {
                      sym[sym_idx].Clear();
                    }
                  }
                  /////////////////////////////
                }
            }

            for (const auto &pos : reexport_shlib_needs_fixup) {
              const auto undef_pos = undefined_name_to_desc.find(pos.second);
              if (undef_pos != undefined_name_to_desc.end()) {
                const uint8_t dylib_ordinal =
                    llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second);
                if (dylib_ordinal > 0 && dylib_ordinal < dylib_files.GetSize())
                  sym[pos.first].SetReExportedSymbolSharedLibrary(
                      dylib_files.GetFileSpecAtIndex(dylib_ordinal - 1));
              }
            }
          }

#endif
  lldb::offset_t nlist_data_offset = 0;

  if (nlist_data.GetByteSize() > 0) {

    const uint64_t max_nsyms = nlist_data.GetByteSize() / nlist_byte_size;
    const uint64_t max_nindirectsyms =
        indirect_symbol_index_data.GetByteSize() / sizeof(uint32_t);

    // If the sym array was not created while parsing the DSC unmapped
    // symbols, create it now.
    if (sym == nullptr) {
      sym = symtab.Resize(
          std::min<uint64_t>(symtab_load_command.nsyms, max_nsyms) +
          std::min<uint64_t>(m_dysymtab.nindirectsyms, max_nindirectsyms));
      num_syms = symtab.GetNumSymbols();
    }

    if (unmapped_local_symbols_found) {
      assert(m_dysymtab.ilocalsym == 0);
      nlist_data_offset += (m_dysymtab.nlocalsym * nlist_byte_size);
      nlist_idx = m_dysymtab.nlocalsym;
    } else {
      nlist_idx = 0;
    }

    typedef llvm::DenseMap<ConstString, uint16_t> UndefinedNameToDescMap;
    typedef llvm::DenseMap<uint32_t, ConstString> SymbolIndexToName;
    UndefinedNameToDescMap undefined_name_to_desc;
    SymbolIndexToName reexport_shlib_needs_fixup;

    // Symtab parsing is a huge mess. Everything is entangled and the code
    // requires access to a ridiculous amount of variables. LLDB depends
    // heavily on the proper merging of symbols and to get that right we need
    // to make sure we have parsed all the debug symbols first. Therefore we
    // invoke the lambda twice, once to parse only the debug symbols and then
    // once more to parse the remaining symbols.
    auto ParseSymbolLambda = [&](struct nlist_64 &nlist, uint32_t nlist_idx,
                                 bool debug_only) {
      const bool is_debug = ((nlist.n_type & N_STAB) != 0);
      if (is_debug != debug_only)
        return true;

      const char *symbol_name_non_abi_mangled = nullptr;
      const char *symbol_name = nullptr;

      if (have_strtab_data) {
        std::optional<llvm::StringRef> name =
            strtab_data.PeekCStr(nlist.n_strx);

        if (!name) {
          // No symbol should be NULL, even the symbols with no string values
          // should have an offset zero which points to an empty C-string
          Debugger::ReportError(llvm::formatv(
              "symbol[{0}] has invalid or unterminated string table offset "
              "{1:x} in {2}, ignoring symbol",
              nlist_idx, nlist.n_strx, module_sp->GetFileSpec().GetPath()));
          return true;
        }
        // The code below spells "no name" as a nullptr.
        if (!name->empty())
          symbol_name = name->data();
      } else {
        const addr_t str_addr = strtab_addr + nlist.n_strx;
        Status str_error;
        if (process->ReadCStringFromMemory(str_addr, memory_symbol_name,
                                           str_error))
          symbol_name = memory_symbol_name.c_str();
      }

      SymbolType type = eSymbolTypeInvalid;
      SectionSP symbol_section;
      bool add_nlist = true;
      bool is_gsym = false;
      bool demangled_is_synthesized = false;
      bool set_value = true;

      assert(sym_idx < num_syms);
      sym[sym_idx].SetDebug(is_debug);

      if (is_debug) {
        switch (nlist.n_type) {
        case N_GSYM: {
          // global symbol: name,,NO_SECT,type,0
          // Sometimes the N_GSYM value contains the address.

          // FIXME: In the .o files, we have a GSYM and a debug symbol for all
          // the ObjC data.  They
          // have the same address, but we want to ensure that we always find
          // only the real symbol, 'cause we don't currently correctly
          // attribute the GSYM one to the ObjCClass/Ivar/MetaClass symbol
          // type.  This is a temporary hack to make sure the ObjectiveC
          // symbols get treated correctly.  To do this right, we should
          // coalesce all the GSYM & global symbols that have the same
          // address.
          is_gsym = true;
          sym[sym_idx].SetExternal(true);

          if (TryParseV2ObjCMetadataSymbol(symbol_name,
                                           symbol_name_non_abi_mangled, type)) {
            demangled_is_synthesized = true;
          } else {
            if (nlist.n_value != 0)
              symbol_section =
                  section_info.GetSection(nlist.n_sect, nlist.n_value);

            type = eSymbolTypeData;
          }
        } break;

        case N_FNAME:
          // procedure name (f77 kludge): name,,NO_SECT,0,0
          type = eSymbolTypeCompiler;
          break;

        case N_FUN:
          // procedure: name,,n_sect,linenumber,address
          if (symbol_name) {
            type = eSymbolTypeCode;
            symbol_section =
                section_info.GetSection(nlist.n_sect, nlist.n_value);

            N_FUN_addr_to_sym_idx.insert(
                std::make_pair(nlist.n_value, sym_idx));
            // We use the current number of symbols in the symbol table in
            // lieu of using nlist_idx in case we ever start trimming entries
            // out
            N_FUN_indexes.push_back(sym_idx);
          } else {
            type = eSymbolTypeCompiler;

            if (!N_FUN_indexes.empty()) {
              // Copy the size of the function into the original STAB entry
              // so we don't have to hunt for it later
              symtab.SymbolAtIndex(N_FUN_indexes.back())
                  ->SetByteSize(nlist.n_value);
              N_FUN_indexes.pop_back();
              // We don't really need the end function STAB as it contains
              // the size which we already placed with the original symbol,
              // so don't add it if we want a minimal symbol table
              add_nlist = false;
            }
          }
          break;

        case N_STSYM:
          // static symbol: name,,n_sect,type,address
          N_STSYM_addr_to_sym_idx.insert(
              std::make_pair(nlist.n_value, sym_idx));
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          if (symbol_name && symbol_name[0]) {
            type = ObjectFile::GetSymbolTypeFromName(symbol_name + 1,
                                                     eSymbolTypeData);
          }
          break;

        case N_LCSYM:
          // .lcomm symbol: name,,n_sect,type,address
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          type = eSymbolTypeCommonBlock;
          break;

        case N_BNSYM:
          // We use the current number of symbols in the symbol table in lieu
          // of using nlist_idx in case we ever start trimming entries out
          // Skip these if we want minimal symbol tables
          add_nlist = false;
          break;

        case N_ENSYM:
          // Set the size of the N_BNSYM to the terminating index of this
          // N_ENSYM so that we can always skip the entire symbol if we need
          // to navigate more quickly at the source level when parsing STABS
          // Skip these if we want minimal symbol tables
          add_nlist = false;
          break;

        case N_OPT:
          // emitted with gcc2_compiled and in gcc source
          type = eSymbolTypeCompiler;
          break;

        case N_RSYM:
          // register sym: name,,NO_SECT,type,register
          type = eSymbolTypeVariable;
          break;

        case N_SLINE:
          // src line: 0,,n_sect,linenumber,address
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          type = eSymbolTypeLineEntry;
          break;

        case N_SSYM:
          // structure elt: name,,NO_SECT,type,struct_offset
          type = eSymbolTypeVariableType;
          break;

        case N_SO:
          // source file name
          type = eSymbolTypeSourceFile;
          if (symbol_name == nullptr) {
            add_nlist = false;
            if (N_SO_index != UINT32_MAX) {
              // Set the size of the N_SO to the terminating index of this
              // N_SO so that we can always skip the entire N_SO if we need
              // to navigate more quickly at the source level when parsing
              // STABS
              symbol_ptr = symtab.SymbolAtIndex(N_SO_index);
              symbol_ptr->SetByteSize(sym_idx);
              symbol_ptr->SetSizeIsSibling(true);
            }
            N_NSYM_indexes.clear();
            N_INCL_indexes.clear();
            N_BRAC_indexes.clear();
            N_COMM_indexes.clear();
            N_FUN_indexes.clear();
            N_SO_index = UINT32_MAX;
          } else {
            // We use the current number of symbols in the symbol table in
            // lieu of using nlist_idx in case we ever start trimming entries
            // out
            const bool N_SO_has_full_path = symbol_name[0] == '/';
            if (N_SO_has_full_path) {
              if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) {
                // We have two consecutive N_SO entries where the first
                // contains a directory and the second contains a full path.
                sym[sym_idx - 1].GetMangled().SetValue(
                    ConstString(symbol_name));
                m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
                add_nlist = false;
              } else {
                // This is the first entry in a N_SO that contains a
                // directory or a full path to the source file
                N_SO_index = sym_idx;
              }
            } else if ((N_SO_index == sym_idx - 1) &&
                       ((sym_idx - 1) < num_syms)) {
              // This is usually the second N_SO entry that contains just the
              // filename, so here we combine it with the first one if we are
              // minimizing the symbol table
              llvm::StringRef so_path = sym[sym_idx - 1]
                                            .GetMangled()
                                            .GetDemangledName()
                                            .GetStringRef();
              if (!so_path.empty()) {
                std::string full_so_path(so_path);
                const size_t double_slash_pos = full_so_path.find("//");
                if (double_slash_pos != std::string::npos) {
                  // The linker has been generating bad N_SO entries with
                  // doubled up paths in the format "%s%s" where the first
                  // string in the DW_AT_comp_dir, and the second is the
                  // directory for the source file so you end up with a path
                  // that looks like "/tmp/src//tmp/src/"
                  FileSpec so_dir(so_path);
                  if (!FileSystem::Instance().Exists(so_dir)) {
                    so_dir.SetFile(&full_so_path[double_slash_pos + 1],
                                   FileSpec::Style::native);
                    if (FileSystem::Instance().Exists(so_dir)) {
                      // Trim off the incorrect path
                      full_so_path.erase(0, double_slash_pos + 1);
                    }
                  }
                }
                if (*full_so_path.rbegin() != '/')
                  full_so_path += '/';
                full_so_path += symbol_name;
                sym[sym_idx - 1].GetMangled().SetValue(
                    ConstString(full_so_path.c_str()));
                add_nlist = false;
                m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
              }
            } else {
              // This could be a relative path to a N_SO
              N_SO_index = sym_idx;
            }
          }
          break;

        case N_OSO:
          // object file name: name,,0,0,st_mtime
          type = eSymbolTypeObjectFile;
          break;

        case N_LSYM:
          // local sym: name,,NO_SECT,type,offset
          type = eSymbolTypeLocal;
          break;

        // INCL scopes
        case N_BINCL:
          // include file beginning: name,,NO_SECT,0,sum We use the current
          // number of symbols in the symbol table in lieu of using nlist_idx
          // in case we ever start trimming entries out
          N_INCL_indexes.push_back(sym_idx);
          type = eSymbolTypeScopeBegin;
          break;

        case N_EINCL:
          // include file end: name,,NO_SECT,0,0
          // Set the size of the N_BINCL to the terminating index of this
          // N_EINCL so that we can always skip the entire symbol if we need
          // to navigate more quickly at the source level when parsing STABS
          if (!N_INCL_indexes.empty()) {
            symbol_ptr = symtab.SymbolAtIndex(N_INCL_indexes.back());
            symbol_ptr->SetByteSize(sym_idx + 1);
            symbol_ptr->SetSizeIsSibling(true);
            N_INCL_indexes.pop_back();
          }
          type = eSymbolTypeScopeEnd;
          break;

        case N_SOL:
          // #included file name: name,,n_sect,0,address
          type = eSymbolTypeHeaderFile;

          // We currently don't use the header files on darwin
          add_nlist = false;
          break;

        case N_PARAMS:
          // compiler parameters: name,,NO_SECT,0,0
          type = eSymbolTypeCompiler;
          break;

        case N_VERSION:
          // compiler version: name,,NO_SECT,0,0
          type = eSymbolTypeCompiler;
          break;

        case N_OLEVEL:
          // compiler -O level: name,,NO_SECT,0,0
          type = eSymbolTypeCompiler;
          break;

        case N_PSYM:
          // parameter: name,,NO_SECT,type,offset
          type = eSymbolTypeVariable;
          break;

        case N_ENTRY:
          // alternate entry: name,,n_sect,linenumber,address
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          type = eSymbolTypeLineEntry;
          break;

        // Left and Right Braces
        case N_LBRAC:
          // left bracket: 0,,NO_SECT,nesting level,address We use the
          // current number of symbols in the symbol table in lieu of using
          // nlist_idx in case we ever start trimming entries out
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          N_BRAC_indexes.push_back(sym_idx);
          type = eSymbolTypeScopeBegin;
          break;

        case N_RBRAC:
          // right bracket: 0,,NO_SECT,nesting level,address Set the size of
          // the N_LBRAC to the terminating index of this N_RBRAC so that we
          // can always skip the entire symbol if we need to navigate more
          // quickly at the source level when parsing STABS
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          if (!N_BRAC_indexes.empty()) {
            symbol_ptr = symtab.SymbolAtIndex(N_BRAC_indexes.back());
            symbol_ptr->SetByteSize(sym_idx + 1);
            symbol_ptr->SetSizeIsSibling(true);
            N_BRAC_indexes.pop_back();
          }
          type = eSymbolTypeScopeEnd;
          break;

        case N_EXCL:
          // deleted include file: name,,NO_SECT,0,sum
          type = eSymbolTypeHeaderFile;
          break;

        // COMM scopes
        case N_BCOMM:
          // begin common: name,,NO_SECT,0,0
          // We use the current number of symbols in the symbol table in lieu
          // of using nlist_idx in case we ever start trimming entries out
          type = eSymbolTypeScopeBegin;
          N_COMM_indexes.push_back(sym_idx);
          break;

        case N_ECOML:
          // end common (local name): 0,,n_sect,0,address
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);
          [[fallthrough]];

        case N_ECOMM:
          // end common: name,,n_sect,0,0
          // Set the size of the N_BCOMM to the terminating index of this
          // N_ECOMM/N_ECOML so that we can always skip the entire symbol if
          // we need to navigate more quickly at the source level when
          // parsing STABS
          if (!N_COMM_indexes.empty()) {
            symbol_ptr = symtab.SymbolAtIndex(N_COMM_indexes.back());
            symbol_ptr->SetByteSize(sym_idx + 1);
            symbol_ptr->SetSizeIsSibling(true);
            N_COMM_indexes.pop_back();
          }
          type = eSymbolTypeScopeEnd;
          break;

        case N_LENG:
          // second stab entry with length information
          type = eSymbolTypeAdditional;
          break;

        default:
          break;
        }
      } else {
        uint8_t n_type = N_TYPE & nlist.n_type;
        sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0);

        switch (n_type) {
        case N_INDR: {
          std::optional<llvm::StringRef> reexport_name_str =
              strtab_data.PeekCStr(nlist.n_value);
          if (reexport_name_str && !reexport_name_str->empty() && symbol_name) {
            type = eSymbolTypeReExported;
            ConstString reexport_name(reexport_name_str->drop_front(
                reexport_name_str->front() == '_' ? 1 : 0));
            sym[sym_idx].SetReExportedSymbolName(reexport_name);
            set_value = false;
            reexport_shlib_needs_fixup[sym_idx] = reexport_name;
            indirect_symbol_names.insert(
                ConstString(symbol_name + ((symbol_name[0] == '_') ? 1 : 0)));
          } else
            type = eSymbolTypeUndefined;
        } break;

        case N_UNDF:
          if (symbol_name && symbol_name[0]) {
            ConstString undefined_name(symbol_name +
                                       ((symbol_name[0] == '_') ? 1 : 0));
            undefined_name_to_desc[undefined_name] = nlist.n_desc;
          }
          [[fallthrough]];

        case N_PBUD:
          type = eSymbolTypeUndefined;
          break;

        case N_ABS:
          type = eSymbolTypeAbsolute;
          break;

        case N_SECT: {
          symbol_section = section_info.GetSection(nlist.n_sect, nlist.n_value);

          if (!symbol_section) {
            // TODO: warn about this?
            add_nlist = false;
            break;
          }

          if (TEXT_eh_frame_sectID == nlist.n_sect) {
            type = eSymbolTypeException;
          } else {
            uint32_t section_type = symbol_section->Get() & SECTION_TYPE;

            switch (section_type) {
            case S_CSTRING_LITERALS:
              type = eSymbolTypeData;
              break; // section with only literal C strings
            case S_4BYTE_LITERALS:
              type = eSymbolTypeData;
              break; // section with only 4 byte literals
            case S_8BYTE_LITERALS:
              type = eSymbolTypeData;
              break; // section with only 8 byte literals
            case S_LITERAL_POINTERS:
              type = eSymbolTypeTrampoline;
              break; // section with only pointers to literals
            case S_NON_LAZY_SYMBOL_POINTERS:
              type = eSymbolTypeTrampoline;
              break; // section with only non-lazy symbol pointers
            case S_LAZY_SYMBOL_POINTERS:
              type = eSymbolTypeTrampoline;
              break; // section with only lazy symbol pointers
            case S_SYMBOL_STUBS:
              type = eSymbolTypeTrampoline;
              break; // section with only symbol stubs, byte size of stub in
                     // the reserved2 field
            case S_MOD_INIT_FUNC_POINTERS:
              type = eSymbolTypeCode;
              break; // section with only function pointers for initialization
            case S_MOD_TERM_FUNC_POINTERS:
              type = eSymbolTypeCode;
              break; // section with only function pointers for termination
            case S_INTERPOSING:
              type = eSymbolTypeTrampoline;
              break; // section with only pairs of function pointers for
                     // interposing
            case S_16BYTE_LITERALS:
              type = eSymbolTypeData;
              break; // section with only 16 byte literals
            case S_DTRACE_DOF:
              type = eSymbolTypeInstrumentation;
              break;
            case S_LAZY_DYLIB_SYMBOL_POINTERS:
              type = eSymbolTypeTrampoline;
              break;
            default:
              switch (symbol_section->GetType()) {
              case lldb::eSectionTypeCode:
                type = eSymbolTypeCode;
                break;
              case eSectionTypeData:
              case eSectionTypeDataCString:         // Inlined C string data
              case eSectionTypeDataCStringPointers: // Pointers to C string
                                                    // data
              case eSectionTypeDataSymbolAddress:   // Address of a symbol in
                                                    // the symbol table
              case eSectionTypeData4:
              case eSectionTypeData8:
              case eSectionTypeData16:
                type = eSymbolTypeData;
                break;
              default:
                break;
              }
              break;
            }

            if (type == eSymbolTypeInvalid) {
              llvm::StringRef symbol_sect_name = symbol_section->GetName();
              if (symbol_section->IsDescendant(text_section_sp.get())) {
                if (symbol_section->IsClear(S_ATTR_PURE_INSTRUCTIONS |
                                            S_ATTR_SELF_MODIFYING_CODE |
                                            S_ATTR_SOME_INSTRUCTIONS))
                  type = eSymbolTypeData;
                else
                  type = eSymbolTypeCode;
              } else if (symbol_section->IsDescendant(data_section_sp.get()) ||
                         symbol_section->IsDescendant(
                             data_dirty_section_sp.get()) ||
                         symbol_section->IsDescendant(
                             data_const_section_sp.get())) {
                if (symbol_sect_name.starts_with("__objc")) {
                  type = eSymbolTypeRuntime;

                  if (TryParseV2ObjCMetadataSymbol(
                          symbol_name, symbol_name_non_abi_mangled, type))
                    demangled_is_synthesized = true;
                } else if (symbol_sect_name.starts_with("__gcc_except_tab")) {
                  type = eSymbolTypeException;
                } else {
                  type = eSymbolTypeData;
                }
              } else if (symbol_sect_name.starts_with("__IMPORT")) {
                type = eSymbolTypeTrampoline;
              } else if (symbol_section->IsDescendant(objc_section_sp.get())) {
                type = eSymbolTypeRuntime;
                if (symbol_name && symbol_name[0] == '.') {
                  llvm::StringRef symbol_name_ref(symbol_name);
                  llvm::StringRef g_objc_v1_prefix_class(
                      ".objc_class_name_");
                  if (symbol_name_ref.starts_with(g_objc_v1_prefix_class)) {
                    symbol_name_non_abi_mangled = symbol_name;
                    symbol_name = symbol_name + g_objc_v1_prefix_class.size();
                    type = eSymbolTypeObjCClass;
                    demangled_is_synthesized = true;
                  }
                }
              }
            }
          }
        } break;
        }
      }

      if (!add_nlist) {
        sym[sym_idx].Clear();
        return true;
      }

      uint64_t symbol_value = nlist.n_value;

      if (symbol_name_non_abi_mangled) {
        sym[sym_idx].GetMangled().SetMangledName(
            ConstString(symbol_name_non_abi_mangled));
        sym[sym_idx].GetMangled().SetDemangledName(ConstString(symbol_name));
      } else {

        if (symbol_name && symbol_name[0] == '_') {
          symbol_name++; // Skip the leading underscore
        }

        if (symbol_name) {
          ConstString const_symbol_name(symbol_name);
          sym[sym_idx].GetMangled().SetValue(const_symbol_name);
        }
      }

      if (is_gsym) {
        const char *gsym_name = sym[sym_idx]
                                    .GetMangled()
                                    .GetName(Mangled::ePreferMangled)
                                    .GetCString();
        if (gsym_name)
          N_GSYM_name_to_sym_idx[gsym_name] = sym_idx;
      }

      if (symbol_section) {
        const addr_t section_file_addr = symbol_section->GetFileAddress();
        symbol_value -= section_file_addr;
      }

      if (!is_debug) {
        if (type == eSymbolTypeCode) {
          // See if we can find a N_FUN entry for any code symbols. If we do
          // find a match, and the name matches, then we can merge the two into
          // just the function symbol to avoid duplicate entries in the symbol
          // table.
          std::pair<ValueToSymbolIndexMap::const_iterator,
                    ValueToSymbolIndexMap::const_iterator>
              range;
          range = N_FUN_addr_to_sym_idx.equal_range(nlist.n_value);
          if (range.first != range.second) {
            for (ValueToSymbolIndexMap::const_iterator pos = range.first;
                 pos != range.second; ++pos) {
              if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) ==
                  sym[pos->second].GetMangled().GetName(
                      Mangled::ePreferMangled)) {
                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
                // We just need the flags from the linker symbol, so put these
                // flags into the N_FUN flags to avoid duplicate symbols in the
                // symbol table.
                sym[pos->second].SetExternal(sym[sym_idx].IsExternal());
                sym[pos->second].SetFlags(nlist.n_type << 16 | nlist.n_desc);
                if (resolver_addresses.find(nlist.n_value) !=
                    resolver_addresses.end())
                  sym[pos->second].SetType(eSymbolTypeResolver);
                sym[sym_idx].Clear();
                return true;
              }
            }
          } else {
            if (resolver_addresses.find(nlist.n_value) !=
                resolver_addresses.end())
              type = eSymbolTypeResolver;
          }
        } else if (type == eSymbolTypeData || type == eSymbolTypeObjCClass ||
                   type == eSymbolTypeObjCMetaClass ||
                   type == eSymbolTypeObjCIVar) {
          // See if we can find a N_STSYM entry for any data symbols. If we do
          // find a match, and the name matches, then we can merge the two into
          // just the Static symbol to avoid duplicate entries in the symbol
          // table.
          std::pair<ValueToSymbolIndexMap::const_iterator,
                    ValueToSymbolIndexMap::const_iterator>
              range;
          range = N_STSYM_addr_to_sym_idx.equal_range(nlist.n_value);
          if (range.first != range.second) {
            for (ValueToSymbolIndexMap::const_iterator pos = range.first;
                 pos != range.second; ++pos) {
              if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) ==
                  sym[pos->second].GetMangled().GetName(
                      Mangled::ePreferMangled)) {
                m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
                // We just need the flags from the linker symbol, so put these
                // flags into the N_STSYM flags to avoid duplicate symbols in
                // the symbol table.
                sym[pos->second].SetExternal(sym[sym_idx].IsExternal());
                sym[pos->second].SetFlags(nlist.n_type << 16 | nlist.n_desc);
                sym[sym_idx].Clear();
                return true;
              }
            }
          } else {
            // Combine N_GSYM stab entries with the non stab symbol.
            const char *gsym_name = sym[sym_idx]
                                        .GetMangled()
                                        .GetName(Mangled::ePreferMangled)
                                        .GetCString();
            if (gsym_name) {
              ConstNameToSymbolIndexMap::const_iterator pos =
                  N_GSYM_name_to_sym_idx.find(gsym_name);
              if (pos != N_GSYM_name_to_sym_idx.end()) {
                const uint32_t GSYM_sym_idx = pos->second;
                m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
                // Copy the address, because often the N_GSYM address has an
                // invalid address of zero when the global is a common symbol.
                sym[GSYM_sym_idx].GetAddressRef() =
                    Address(symbol_section, symbol_value);
                add_symbol_addr(
                    sym[GSYM_sym_idx].GetAddress().GetFileAddress());
                // We just need the flags from the linker symbol, so put these
                // flags into the N_GSYM flags to avoid duplicate symbols in
                // the symbol table.
                sym[GSYM_sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
                sym[sym_idx].Clear();
                return true;
              }
            }
          }
        }
      }

      sym[sym_idx].SetID(nlist_idx);
      sym[sym_idx].SetType(type);
      if (set_value) {
        sym[sym_idx].GetAddressRef() = Address(symbol_section, symbol_value);
        if (symbol_section)
          add_symbol_addr(sym[sym_idx].GetAddress().GetFileAddress());
      }
      sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
      if (nlist.n_desc & N_WEAK_REF)
        sym[sym_idx].SetIsWeak(true);

      if (demangled_is_synthesized)
        sym[sym_idx].SetDemangledNameIsSynthesized(true);

      ++sym_idx;
      return true;
    };

    // First parse all the nlists but don't process them yet. See the next
    // comment for an explanation why.
    std::vector<struct nlist_64> nlists;
    nlists.reserve(std::min<uint64_t>(symtab_load_command.nsyms, max_nsyms));
    for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) {
      if (auto nlist =
              ParseNList(nlist_data, nlist_data_offset, nlist_byte_size))
        nlists.push_back(*nlist);
      else
        break;
    }

    // Now parse all the debug symbols. This is needed to merge non-debug
    // symbols in the next step. Non-debug symbols are always coalesced into
    // the debug symbol. Doing this in one step would mean that some symbols
    // won't be merged.
    nlist_idx = 0;
    for (auto &nlist : nlists) {
      if (!ParseSymbolLambda(nlist, nlist_idx++, DebugSymbols))
        break;
    }

    // Finally parse all the non debug symbols.
    nlist_idx = 0;
    for (auto &nlist : nlists) {
      if (!ParseSymbolLambda(nlist, nlist_idx++, NonDebugSymbols))
        break;
    }

    for (const auto &pos : reexport_shlib_needs_fixup) {
      const auto undef_pos = undefined_name_to_desc.find(pos.second);
      if (undef_pos != undefined_name_to_desc.end()) {
        const uint8_t dylib_ordinal =
            llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second);
        if (dylib_ordinal > 0 && dylib_ordinal < dylib_files.GetSize())
          sym[pos.first].SetReExportedSymbolSharedLibrary(
              dylib_files.GetFileSpecAtIndex(dylib_ordinal - 1));
      }
    }
  }

  // Count how many trie symbols we'll add to the symbol table
  int trie_symbol_table_augment_count = 0;
  for (auto &e : external_sym_trie_entries) {
    if (!symbols_added.contains(e.entry.address))
      trie_symbol_table_augment_count++;
  }

  if (num_syms < sym_idx + trie_symbol_table_augment_count) {
    num_syms = sym_idx + trie_symbol_table_augment_count;
    sym = symtab.Resize(num_syms);
  }
  uint32_t synthetic_sym_id = symtab_load_command.nsyms;

  // Add symbols from the trie to the symbol table.
  for (auto &e : external_sym_trie_entries) {
    if (symbols_added.contains(e.entry.address))
      continue;

    // Find the section that this trie address is in, use that to annotate
    // symbol type as we add the trie address and name to the symbol table.
    Address symbol_addr;
    if (module_sp->ResolveFileAddress(e.entry.address, symbol_addr)) {
      SectionSP symbol_section(symbol_addr.GetSection());
      const char *symbol_name = e.entry.name.GetCString();
      bool demangled_is_synthesized = false;
      SymbolType type =
          GetSymbolType(symbol_name, demangled_is_synthesized, text_section_sp,
                        data_section_sp, data_dirty_section_sp,
                        data_const_section_sp, symbol_section);

      sym[sym_idx].SetType(type);
      if (symbol_section) {
        sym[sym_idx].SetID(synthetic_sym_id++);
        sym[sym_idx].GetMangled().SetMangledName(ConstString(symbol_name));
        if (demangled_is_synthesized)
          sym[sym_idx].SetDemangledNameIsSynthesized(true);
        sym[sym_idx].SetIsSynthetic(true);
        sym[sym_idx].SetExternal(true);
        sym[sym_idx].GetAddressRef() = symbol_addr;
        add_symbol_addr(symbol_addr.GetFileAddress());
        if (e.entry.flags & TRIE_SYMBOL_IS_THUMB)
          sym[sym_idx].SetFlags(MACHO_NLIST_ARM_SYMBOL_IS_THUMB);
        ++sym_idx;
      }
    }
  }

  if (function_starts_count > 0) {
    uint32_t num_synthetic_function_symbols = 0;
    for (i = 0; i < function_starts_count; ++i) {
      if (!symbols_added.contains(function_starts.GetEntryRef(i).addr))
        ++num_synthetic_function_symbols;
    }

    if (num_synthetic_function_symbols > 0) {
      if (num_syms < sym_idx + num_synthetic_function_symbols) {
        num_syms = sym_idx + num_synthetic_function_symbols;
        sym = symtab.Resize(num_syms);
      }
      for (i = 0; i < function_starts_count; ++i) {
        const FunctionStarts::Entry *func_start_entry =
            function_starts.GetEntryAtIndex(i);
        if (!symbols_added.contains(func_start_entry->addr)) {
          addr_t symbol_file_addr = func_start_entry->addr;
          uint32_t symbol_flags = 0;
          if (func_start_entry->data)
            symbol_flags = MACHO_NLIST_ARM_SYMBOL_IS_THUMB;
          Address symbol_addr;
          if (module_sp->ResolveFileAddress(symbol_file_addr, symbol_addr)) {
            SectionSP symbol_section(symbol_addr.GetSection());
            if (symbol_section) {
              sym[sym_idx].SetID(synthetic_sym_id++);
              // Don't set the name for any synthetic symbols, the Symbol
              // object will generate one if needed when the name is accessed
              // via accessors.
              sym[sym_idx].GetMangled().SetDemangledName(ConstString());
              sym[sym_idx].SetType(eSymbolTypeCode);
              sym[sym_idx].SetIsSynthetic(true);
              sym[sym_idx].GetAddressRef() = symbol_addr;
              add_symbol_addr(symbol_addr.GetFileAddress());
              if (symbol_flags)
                sym[sym_idx].SetFlags(symbol_flags);
              ++sym_idx;
            }
          }
        }
      }
    }
  }

  // Trim our symbols down to just what we ended up with after removing any
  // symbols.
  if (sym_idx < num_syms) {
    num_syms = sym_idx;
    sym = symtab.Resize(num_syms);
  }

  // Now synthesize indirect symbols
  if (m_dysymtab.nindirectsyms != 0) {
    if (indirect_symbol_index_data.GetByteSize()) {
      NListIndexToSymbolIndexMap::const_iterator end_index_pos =
          m_nlist_idx_to_sym_idx.end();

      for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size();
           ++sect_idx) {
        if ((m_mach_sections[sect_idx].flags & SECTION_TYPE) ==
            S_SYMBOL_STUBS) {
          uint32_t symbol_stub_byte_size = m_mach_sections[sect_idx].reserved2;
          if (symbol_stub_byte_size == 0)
            continue;

          const uint32_t num_symbol_stubs =
              m_mach_sections[sect_idx].size / symbol_stub_byte_size;

          if (num_symbol_stubs == 0)
            continue;

          const uint32_t symbol_stub_index_offset =
              m_mach_sections[sect_idx].reserved1;
          for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx) {
            const uint32_t symbol_stub_index =
                symbol_stub_index_offset + stub_idx;
            const lldb::addr_t symbol_stub_addr =
                m_mach_sections[sect_idx].addr +
                (stub_idx * symbol_stub_byte_size);
            lldb::offset_t symbol_stub_offset = symbol_stub_index * 4;
            if (indirect_symbol_index_data.ValidOffsetForDataOfSize(
                    symbol_stub_offset, 4)) {
              const uint32_t stub_sym_id =
                  indirect_symbol_index_data.GetU32(&symbol_stub_offset);
              if (stub_sym_id & (INDIRECT_SYMBOL_ABS | INDIRECT_SYMBOL_LOCAL))
                continue;

              NListIndexToSymbolIndexMap::const_iterator index_pos =
                  m_nlist_idx_to_sym_idx.find(stub_sym_id);
              Symbol *stub_symbol = nullptr;
              if (index_pos != end_index_pos) {
                // We have a remapping from the original nlist index to a
                // current symbol index, so just look this up by index
                stub_symbol = symtab.SymbolAtIndex(index_pos->second);
              } else {
                // We need to lookup a symbol using the original nlist symbol
                // index since this index is coming from the S_SYMBOL_STUBS
                stub_symbol = symtab.FindSymbolByID(stub_sym_id);
              }

              if (stub_symbol) {
                Address so_addr(symbol_stub_addr, section_list);

                if (stub_symbol->GetType() == eSymbolTypeUndefined) {
                  // Change the external symbol into a trampoline that makes
                  // sense These symbols were N_UNDF N_EXT, and are useless
                  // to us, so we can re-use them so we don't have to make up
                  // a synthetic symbol for no good reason.
                  if (resolver_addresses.find(symbol_stub_addr) ==
                      resolver_addresses.end())
                    stub_symbol->SetType(eSymbolTypeTrampoline);
                  else
                    stub_symbol->SetType(eSymbolTypeResolver);
                  stub_symbol->SetExternal(false);
                  stub_symbol->GetAddressRef() = so_addr;
                  stub_symbol->SetByteSize(symbol_stub_byte_size);
                } else {
                  // Make a synthetic symbol to describe the trampoline stub
                  Mangled stub_symbol_mangled_name(stub_symbol->GetMangled());
                  if (sym_idx >= num_syms) {
                    sym = symtab.Resize(++num_syms);
                    stub_symbol = nullptr; // this pointer no longer valid
                  }
                  sym[sym_idx].SetID(synthetic_sym_id++);
                  sym[sym_idx].GetMangled() = stub_symbol_mangled_name;
                  if (resolver_addresses.find(symbol_stub_addr) ==
                      resolver_addresses.end())
                    sym[sym_idx].SetType(eSymbolTypeTrampoline);
                  else
                    sym[sym_idx].SetType(eSymbolTypeResolver);
                  sym[sym_idx].SetIsSynthetic(true);
                  sym[sym_idx].GetAddressRef() = so_addr;
                  add_symbol_addr(so_addr.GetFileAddress());
                  sym[sym_idx].SetByteSize(symbol_stub_byte_size);
                  ++sym_idx;
                }
              } else {
                LLDB_LOGF(log,
                          "warning: symbol stub referencing symbol table "
                          "symbol %u that isn't in our minimal symbol table, "
                          "fix this!!!",
                          stub_sym_id);
              }
            }
          }
        }
      }
    }
  }

  if (!reexport_trie_entries.empty()) {
    for (const auto &e : reexport_trie_entries) {
      if (e.entry.import_name) {
        // Only add indirect symbols from the Trie entries if we didn't have
        // a N_INDR nlist entry for this already
        if (indirect_symbol_names.find(e.entry.name) ==
            indirect_symbol_names.end()) {
          // Make a synthetic symbol to describe re-exported symbol.
          if (sym_idx >= num_syms)
            sym = symtab.Resize(++num_syms);
          sym[sym_idx].SetID(synthetic_sym_id++);
          sym[sym_idx].GetMangled() = Mangled(e.entry.name);
          sym[sym_idx].SetType(eSymbolTypeReExported);
          sym[sym_idx].SetIsSynthetic(true);
          sym[sym_idx].SetReExportedSymbolName(e.entry.import_name);
          if (e.entry.other > 0 && e.entry.other <= dylib_files.GetSize()) {
            sym[sym_idx].SetReExportedSymbolSharedLibrary(
                dylib_files.GetFileSpecAtIndex(e.entry.other - 1));
          }
          ++sym_idx;
        }
      }
    }
  }
}

void ObjectFileMachO::Dump(Stream *s) {
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    s->Printf("%p: ", static_cast<void *>(this));
    s->Indent();
    if (m_header.magic == MH_MAGIC_64 || m_header.magic == MH_CIGAM_64)
      s->PutCString("ObjectFileMachO64");
    else
      s->PutCString("ObjectFileMachO32");

    *s << ", file = '" << m_file;
    ModuleSpecList all_specs;
    ModuleSpec base_spec;
    GetAllArchSpecs(m_header, *m_data_nsp,
                    MachHeaderSizeFromMagic(m_header.magic), base_spec,
                    all_specs);
    for (unsigned i = 0, e = all_specs.GetSize(); i != e; ++i) {
      *s << "', triple";
      if (e)
        s->Printf("[%d]", i);
      *s << " = ";
      *s << all_specs.GetModuleSpecRefAtIndex(i)
                .GetArchitecture()
                .GetTriple()
                .getTriple();
    }
    *s << "\n";
    SectionList *sections = GetSectionList();
    if (sections)
      sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
                     UINT32_MAX);

    if (m_symtab_up)
      m_symtab_up->Dump(s, nullptr, eSortOrderNone);
  }
}

UUID ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
                              const lldb_private::DataExtractor &data,
                              lldb::offset_t lc_offset) {
  uint32_t i;
  llvm::MachO::uuid_command load_cmd;

  lldb::offset_t offset = lc_offset;
  for (i = 0; i < header.ncmds; ++i) {
    const lldb::offset_t cmd_offset = offset;
    if (!ReadMachOCommand(data, offset, load_cmd))
      break;

    if (load_cmd.cmd == LC_UUID) {
      const uint8_t *uuid_bytes = data.PeekData(offset, 16);

      if (uuid_bytes) {
        // OpenCL on Mac OS X uses the same UUID for each of its object files.
        // We pretend these object files have no UUID to prevent crashing.

        const uint8_t opencl_uuid[] = {0x8c, 0x8e, 0xb3, 0x9b, 0x3b, 0xa8,
                                       0x4b, 0x16, 0xb6, 0xa4, 0x27, 0x63,
                                       0xbb, 0x14, 0xf0, 0x0d};

        if (!memcmp(uuid_bytes, opencl_uuid, 16))
          return UUID();

        return UUID(uuid_bytes, 16);
      }
      return UUID();
    }
    offset = cmd_offset + load_cmd.cmdsize;
  }
  return UUID();
}

static llvm::StringRef GetOSName(uint32_t cmd) {
  switch (cmd) {
  case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
    return llvm::Triple::getOSTypeName(llvm::Triple::IOS);
  case llvm::MachO::LC_VERSION_MIN_MACOSX:
    return llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
  case llvm::MachO::LC_VERSION_MIN_TVOS:
    return llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
  case llvm::MachO::LC_VERSION_MIN_WATCHOS:
    return llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
  default:
    llvm_unreachable("unexpected LC_VERSION load command");
  }
}

namespace {
struct OSEnv {
  llvm::StringRef os_type;
  llvm::StringRef environment;
  OSEnv(uint32_t cmd) {
    switch (cmd) {
    case llvm::MachO::PLATFORM_MACOS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
      return;
    case llvm::MachO::PLATFORM_IOS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
      return;
    case llvm::MachO::PLATFORM_TVOS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
      return;
    case llvm::MachO::PLATFORM_WATCHOS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
      return;
    case llvm::MachO::PLATFORM_BRIDGEOS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::BridgeOS);
      return;
    case llvm::MachO::PLATFORM_DRIVERKIT:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::DriverKit);
      return;
    case llvm::MachO::PLATFORM_MACCATALYST:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
      environment = llvm::Triple::getEnvironmentTypeName(llvm::Triple::MacABI);
      return;
    case llvm::MachO::PLATFORM_IOSSIMULATOR:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
      environment =
          llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
      return;
    case llvm::MachO::PLATFORM_TVOSSIMULATOR:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
      environment =
          llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
      return;
    case llvm::MachO::PLATFORM_WATCHOSSIMULATOR:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
      environment =
          llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
      return;
    case llvm::MachO::PLATFORM_XROS:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::XROS);
      return;
    case llvm::MachO::PLATFORM_XROS_SIMULATOR:
      os_type = llvm::Triple::getOSTypeName(llvm::Triple::XROS);
      environment =
          llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
      return;
    default: {
      Log *log(GetLog(LLDBLog::Symbols | LLDBLog::Process));
      LLDB_LOGF(log, "unsupported platform in LC_BUILD_VERSION");
    }
    }
  }
};

struct MinOS {
  uint32_t major_version, minor_version, patch_version;
  MinOS(uint32_t version)
      : major_version(version >> 16), minor_version((version >> 8) & 0xffu),
        patch_version(version & 0xffu) {}
};
} // namespace

void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header,
                                      const lldb_private::DataExtractor &data,
                                      lldb::offset_t lc_offset,
                                      ModuleSpec &base_spec,
                                      lldb_private::ModuleSpecList &all_specs) {
  auto &base_arch = base_spec.GetArchitecture();
  base_arch.SetArchitecture(eArchTypeMachO, header.cputype, header.cpusubtype);
  if (!base_arch.IsValid())
    return;

  bool found_any = false;
  auto add_triple = [&](const llvm::Triple &triple) {
    auto spec = base_spec;
    spec.GetArchitecture().GetTriple() = triple;
    if (spec.GetArchitecture().IsValid()) {
      spec.GetUUID() = ObjectFileMachO::GetUUID(header, data, lc_offset);
      all_specs.Append(spec);
      found_any = true;
    }
  };

  // Set OS to an unspecified unknown or a "*" so it can match any OS
  llvm::Triple base_triple = base_arch.GetTriple();
  base_triple.setOS(llvm::Triple::UnknownOS);
  base_triple.setOSName(llvm::StringRef());

  if (header.filetype == MH_PRELOAD) {
    if (header.cputype == CPU_TYPE_ARM) {
      // If this is a 32-bit arm binary, and it's a standalone binary, force
      // the Vendor to Apple so we don't accidentally pick up the generic
      // armv7 ABI at runtime.  Apple's armv7 ABI always uses r7 for the
      // frame pointer register; most other armv7 ABIs use a combination of
      // r7 and r11.
      base_triple.setVendor(llvm::Triple::Apple);
    } else {
      // Set vendor to an unspecified unknown or a "*" so it can match any
      // vendor This is required for correct behavior of EFI debugging on
      // x86_64
      base_triple.setVendor(llvm::Triple::UnknownVendor);
      base_triple.setVendorName(llvm::StringRef());
    }
    return add_triple(base_triple);
  }

  llvm::MachO::load_command load_cmd;

  // See if there is an LC_VERSION_MIN_* load command that can give
  // us the OS type.
  lldb::offset_t offset = lc_offset;
  for (uint32_t i = 0; i < header.ncmds; ++i) {
    const lldb::offset_t cmd_offset = offset;
    if (!ReadMachOCommand(data, offset, load_cmd))
      break;

    llvm::MachO::version_min_command version_min;
    switch (load_cmd.cmd) {
    case llvm::MachO::LC_VERSION_MIN_MACOSX:
    case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
    case llvm::MachO::LC_VERSION_MIN_TVOS:
    case llvm::MachO::LC_VERSION_MIN_WATCHOS: {
      if (load_cmd.cmdsize != sizeof(version_min))
        break;
      if (data.ExtractBytes(cmd_offset, sizeof(version_min),
                            data.GetByteOrder(), &version_min) == 0)
        break;
      MinOS min_os(version_min.version);
      llvm::SmallString<32> os_name;
      llvm::raw_svector_ostream os(os_name);
      os << GetOSName(load_cmd.cmd) << min_os.major_version << '.'
         << min_os.minor_version << '.' << min_os.patch_version;

      auto triple = base_triple;
      triple.setOSName(os.str());

      // Disambiguate legacy simulator platforms.
      if (load_cmd.cmd != llvm::MachO::LC_VERSION_MIN_MACOSX &&
          (base_triple.getArch() == llvm::Triple::x86_64 ||
           base_triple.getArch() == llvm::Triple::x86)) {
        // The combination of legacy LC_VERSION_MIN load command and
        // x86 architecture always indicates a simulator environment.
        // The combination of LC_VERSION_MIN and arm architecture only
        // appears for native binaries. Back-deploying simulator
        // binaries on Apple Silicon Macs use the modern unambigous
        // LC_BUILD_VERSION load commands; no special handling required.
        triple.setEnvironment(llvm::Triple::Simulator);
      }
      add_triple(triple);
      break;
    }
    default:
      break;
    }

    offset = cmd_offset + load_cmd.cmdsize;
  }

  // See if there are LC_BUILD_VERSION load commands that can give
  // us the OS type.
  offset = lc_offset;
  for (uint32_t i = 0; i < header.ncmds; ++i) {
    const lldb::offset_t cmd_offset = offset;
    if (!ReadMachOCommand(data, offset, load_cmd))
      break;

    do {
      if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) {
        llvm::MachO::build_version_command build_version;
        if (load_cmd.cmdsize < sizeof(build_version)) {
          // Malformed load command.
          break;
        }
        if (data.ExtractBytes(cmd_offset, sizeof(build_version),
                              data.GetByteOrder(), &build_version) == 0)
          break;
        MinOS min_os(build_version.minos);
        OSEnv os_env(build_version.platform);
        llvm::SmallString<16> os_name;
        llvm::raw_svector_ostream os(os_name);
        os << os_env.os_type << min_os.major_version << '.'
           << min_os.minor_version << '.' << min_os.patch_version;
        auto triple = base_triple;
        triple.setOSName(os.str());
        os_name.clear();
        if (!os_env.environment.empty())
          triple.setEnvironmentName(os_env.environment);
        add_triple(triple);
      }
    } while (false);
    offset = cmd_offset + load_cmd.cmdsize;
  }

  if (!found_any) {
    add_triple(base_triple);
  }
}

ArchSpec ObjectFileMachO::GetArchitecture(
    ModuleSP module_sp, const llvm::MachO::mach_header &header,
    const lldb_private::DataExtractor &data, lldb::offset_t lc_offset) {
  ModuleSpecList all_specs;
  ModuleSpec base_spec;
  GetAllArchSpecs(header, data, MachHeaderSizeFromMagic(header.magic),
                  base_spec, all_specs);

  // If the object file offers multiple alternative load commands,
  // pick the one that matches the module.
  if (module_sp) {
    const ArchSpec &module_arch = module_sp->GetArchitecture();
    for (unsigned i = 0, e = all_specs.GetSize(); i != e; ++i) {
      ArchSpec mach_arch =
          all_specs.GetModuleSpecRefAtIndex(i).GetArchitecture();
      if (module_arch.IsCompatibleMatch(mach_arch))
        return mach_arch;
    }
  }

  // Return the first arch we found.
  if (all_specs.GetSize() == 0)
    return {};
  return all_specs.GetModuleSpecRefAtIndex(0).GetArchitecture();
}

UUID ObjectFileMachO::GetUUID() {
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
    return GetUUID(m_header, *m_data_nsp, offset);
  }
  return UUID();
}

uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
  ModuleSP module_sp = GetModule();
  if (!module_sp)
    return 0;

  uint32_t count = 0;
  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
  llvm::MachO::load_command load_cmd;
  lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
  std::vector<std::string> rpath_paths;
  std::vector<std::string> rpath_relative_paths;
  std::vector<std::string> at_exec_relative_paths;
  uint32_t i;
  for (i = 0; i < m_header.ncmds; ++i) {
    const uint32_t cmd_offset = offset;
    if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
      break;

    switch (load_cmd.cmd) {
    case LC_RPATH:
    case LC_LOAD_DYLIB:
    case LC_LOAD_WEAK_DYLIB:
    case LC_REEXPORT_DYLIB:
    case LC_LOAD_DYLINKER:
    case LC_LOADFVMLIB:
    case LC_LOAD_UPWARD_DYLIB: {
      uint32_t name_offset = cmd_offset + m_data_nsp->GetU32(&offset);
      // For LC_LOAD_DYLIB there is an alternate encoding
      // which adds a uint32_t `flags` field for `DYLD_USE_*`
      // flags.  This can be detected by a timestamp field with
      // the `DYLIB_USE_MARKER` constant value.
      bool is_delayed_init = false;
      uint32_t use_command_marker = m_data_nsp->GetU32(&offset);
      if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */) {
        offset += 4; /* uint32_t current_version */
        offset += 4; /* uint32_t compat_version */
        uint32_t flags = m_data_nsp->GetU32(&offset);
        // If this LC_LOAD_DYLIB is marked delay-init,
        // don't report it as a dependent library -- it
        // may be loaded in the process at some point,
        // but will most likely not be load at launch.
        if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */)
          is_delayed_init = true;
      }
      std::optional<llvm::StringRef> maybe_path =
          m_data_nsp->PeekCStr(name_offset);
      if (maybe_path && !is_delayed_init) {
        llvm::StringRef path = *maybe_path;
        if (load_cmd.cmd == LC_RPATH)
          rpath_paths.push_back(path.str());
        else if (path.consume_front("@rpath"))
          rpath_relative_paths.push_back(path.str());
        else if (path.consume_front("@executable_path"))
          at_exec_relative_paths.push_back(path.str());
        else if (!path.starts_with("@")) {
          FileSpec file_spec(path);
          if (files.AppendIfUnique(file_spec))
            count++;
        }
      }
    } break;

    default:
      break;
    }
    offset = cmd_offset + load_cmd.cmdsize;
  }

  FileSpec this_file_spec(m_file);
  FileSystem::Instance().Resolve(this_file_spec);

  if (!rpath_paths.empty()) {
    // Fixup all LC_RPATH values to be absolute paths.
    const std::string this_directory = this_file_spec.GetDirectory().str();
    for (auto &rpath : rpath_paths) {
      if (llvm::StringRef(rpath).starts_with(g_loader_path))
        rpath = this_directory + rpath.substr(g_loader_path.size());
      else if (llvm::StringRef(rpath).starts_with(g_executable_path))
        rpath = this_directory + rpath.substr(g_executable_path.size());
    }

    for (const auto &rpath_relative_path : rpath_relative_paths) {
      for (const auto &rpath : rpath_paths) {
        std::string path = rpath;
        path += rpath_relative_path;
        // It is OK to resolve this path because we must find a file on disk
        // for us to accept it anyway if it is rpath relative.
        FileSpec file_spec(path);
        FileSystem::Instance().Resolve(file_spec);
        if (FileSystem::Instance().Exists(file_spec) &&
            files.AppendIfUnique(file_spec)) {
          count++;
          break;
        }
      }
    }
  }

  // We may have @executable_paths but no RPATHS.  Figure those out here.
  // Only do this if this object file is the executable.  We have no way to
  // get back to the actual executable otherwise, so we won't get the right
  // path.
  if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) {
    FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent();
    for (const auto &at_exec_relative_path : at_exec_relative_paths) {
      FileSpec file_spec =
          exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
      if (FileSystem::Instance().Exists(file_spec) &&
          files.AppendIfUnique(file_spec))
        count++;
    }
  }
  return count;
}

lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
  // If the object file is not an executable it can't hold the entry point.
  // m_entry_point_address is initialized to an invalid address, so we can just
  // return that. If m_entry_point_address is valid it means we've found it
  // already, so return the cached value.

  if ((!IsExecutable() && !IsDynamicLoader()) ||
      m_entry_point_address.IsValid()) {
    return m_entry_point_address;
  }

  // Otherwise, look for the UnixThread or Thread command.  The data for the
  // Thread command is given in /usr/include/mach-o.h, but it is basically:
  //
  //  uint32_t flavor  - this is the flavor argument you would pass to
  //  thread_get_state
  //  uint32_t count   - this is the count of longs in the thread state data
  //  struct XXX_thread_state state - this is the structure from
  //  <machine/thread_status.h> corresponding to the flavor.
  //  <repeat this trio>
  //
  // So we just keep reading the various register flavors till we find the GPR
  // one, then read the PC out of there.
  // FIXME: We will need to have a "RegisterContext data provider" class at some
  // point that can get all the registers
  // out of data in this form & attach them to a given thread.  That should
  // underlie the MacOS X User process plugin, and we'll also need it for the
  // MacOS X Core File process plugin.  When we have that we can also use it
  // here.
  //
  // For now we hard-code the offsets and flavors we need:
  //
  //

  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    llvm::MachO::load_command load_cmd;
    lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
    uint32_t i;
    lldb::addr_t start_address = LLDB_INVALID_ADDRESS;
    bool done = false;

    for (i = 0; i < m_header.ncmds; ++i) {
      const lldb::offset_t cmd_offset = offset;
      if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
        break;

      switch (load_cmd.cmd) {
      case LC_UNIXTHREAD:
      case LC_THREAD: {
        while (offset < cmd_offset + load_cmd.cmdsize) {
          uint32_t flavor = m_data_nsp->GetU32(&offset);
          uint32_t count = m_data_nsp->GetU32(&offset);
          if (count == 0) {
            // We've gotten off somehow, log and exit;
            return m_entry_point_address;
          }

          switch (m_header.cputype) {
          case llvm::MachO::CPU_TYPE_ARM:
            if (flavor == 1 ||
                flavor == 9) // ARM_THREAD_STATE/ARM_THREAD_STATE32
                             // from mach/arm/thread_status.h
            {
              offset += 60; // This is the offset of pc in the GPR thread state
                            // data structure.
              start_address = m_data_nsp->GetU32(&offset);
              done = true;
            }
            break;
          case llvm::MachO::CPU_TYPE_ARM64:
          case llvm::MachO::CPU_TYPE_ARM64_32:
            if (flavor == 6) // ARM_THREAD_STATE64 from mach/arm/thread_status.h
            {
              offset += 256; // This is the offset of pc in the GPR thread state
                             // data structure.
              start_address = m_data_nsp->GetU64(&offset);
              done = true;
            }
            break;
          case llvm::MachO::CPU_TYPE_X86_64:
            if (flavor ==
                4) // x86_THREAD_STATE64 from mach/i386/thread_status.h
            {
              offset += 16 * 8; // This is the offset of rip in the GPR thread
                                // state data structure.
              start_address = m_data_nsp->GetU64(&offset);
              done = true;
            }
            break;
          default:
            return m_entry_point_address;
          }
          // Haven't found the GPR flavor yet, skip over the data for this
          // flavor:
          if (done)
            break;
          offset += count * 4;
        }
      } break;
      case LC_MAIN: {
        uint64_t entryoffset = m_data_nsp->GetU64(&offset);
        SectionSP text_segment_sp =
            GetSectionList()->FindSectionByName(GetSegmentNameTEXT());
        if (text_segment_sp) {
          done = true;
          start_address = text_segment_sp->GetFileAddress() + entryoffset;
        }
      } break;

      default:
        break;
      }
      if (done)
        break;

      // Go to the next load command:
      offset = cmd_offset + load_cmd.cmdsize;
    }

    if (start_address == LLDB_INVALID_ADDRESS && IsDynamicLoader()) {
      if (GetSymtab()) {
        const Symbol *dyld_start_sym =
            GetSymtab()->FindFirstSymbolWithNameAndType(
                ConstString("_dyld_start"), SymbolType::eSymbolTypeCode,
                Symtab::eDebugAny, Symtab::eVisibilityAny);
        if (dyld_start_sym && dyld_start_sym->GetAddress().IsValid()) {
          start_address = dyld_start_sym->GetAddress().GetFileAddress();
        }
      }
    }

    if (start_address != LLDB_INVALID_ADDRESS) {
      // We got the start address from the load commands, so now resolve that
      // address in the sections of this ObjectFile:
      if (!m_entry_point_address.ResolveAddressUsingFileSections(
              start_address, GetSectionList())) {
        m_entry_point_address.Clear();
      }
    } else {
      // We couldn't read the UnixThread load command - maybe it wasn't there.
      // As a fallback look for the "start" symbol in the main executable.

      ModuleSP module_sp(GetModule());

      if (module_sp) {
        SymbolContextList contexts;
        SymbolContext context;
        module_sp->FindSymbolsWithNameAndType(ConstString("start"),
                                              eSymbolTypeCode, contexts);
        if (contexts.GetSize()) {
          if (contexts.GetContextAtIndex(0, context))
            m_entry_point_address = context.symbol->GetAddress();
        }
      }
    }
  }

  return m_entry_point_address;
}

lldb_private::Address ObjectFileMachO::GetBaseAddress() {
  lldb_private::Address header_addr;
  SectionList *section_list = GetSectionList();
  if (section_list) {
    SectionSP text_segment_sp(
        section_list->FindSectionByName(GetSegmentNameTEXT()));
    if (text_segment_sp)
      header_addr = Address(text_segment_sp, /*offset=*/0);
  }
  return header_addr;
}

uint32_t ObjectFileMachO::GetNumThreadContexts() {
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    if (!m_thread_context_offsets_valid) {
      m_thread_context_offsets_valid = true;
      lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
      FileRangeArray::Entry file_range;
      llvm::MachO::thread_command thread_cmd;
      for (uint32_t i = 0; i < m_header.ncmds; ++i) {
        const uint32_t cmd_offset = offset;
        if (!ReadMachOCommand(*m_data_nsp, offset, thread_cmd))
          break;

        if (thread_cmd.cmd == LC_THREAD) {
          file_range.SetRangeBase(offset);
          file_range.SetByteSize(thread_cmd.cmdsize - 8);
          m_thread_context_offsets.Append(file_range);
        }
        offset = cmd_offset + thread_cmd.cmdsize;
      }
    }
  }
  return m_thread_context_offsets.GetSize();
}

std::vector<std::tuple<offset_t, offset_t>>
ObjectFileMachO::FindLC_NOTEByName(std::string name) {
  std::vector<std::tuple<offset_t, offset_t>> results;
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

    offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
    for (uint32_t i = 0; i < m_header.ncmds; ++i) {
      const uint32_t cmd_offset = offset;
      llvm::MachO::load_command lc = {};
      if (!ReadMachOCommand(*m_data_nsp, offset, lc))
        break;
      if (lc.cmd == LC_NOTE) {
        char data_owner[17];
        m_data_nsp->CopyData(offset, 16, data_owner);
        data_owner[16] = '\0';
        offset += 16;

        if (name == data_owner) {
          offset_t payload_offset = m_data_nsp->GetU64_unchecked(&offset);
          offset_t payload_size = m_data_nsp->GetU64_unchecked(&offset);
          results.push_back({payload_offset, payload_size});
        }
      }
      offset = cmd_offset + lc.cmdsize;
    }
  }
  return results;
}

std::string ObjectFileMachO::GetIdentifierString() {
  Log *log(
      GetLog(LLDBLog::Symbols | LLDBLog::Process | LLDBLog::DynamicLoader));
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

    auto lc_notes = FindLC_NOTEByName("kern ver str");
    for (auto lc_note : lc_notes) {
      offset_t payload_offset = std::get<0>(lc_note);
      offset_t payload_size = std::get<1>(lc_note);
      uint32_t version;
      if (m_data_nsp->GetU32(&payload_offset, &version, 1) != nullptr) {
        if (version == 1) {
          uint32_t strsize = payload_size - sizeof(uint32_t);
          std::string result(strsize, '\0');
          m_data_nsp->CopyData(payload_offset, strsize, result.data());
          LLDB_LOGF(log, "LC_NOTE 'kern ver str' found with text '%s'",
                    result.c_str());
          return result;
        }
      }
    }

    // Second, make a pass over the load commands looking for an obsolete
    // LC_IDENT load command.
    offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
    for (uint32_t i = 0; i < m_header.ncmds; ++i) {
      const uint32_t cmd_offset = offset;
      llvm::MachO::ident_command ident_command;
      if (!ReadMachOCommand(*m_data_nsp, offset, ident_command))
        break;
      if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
        std::string result(ident_command.cmdsize, '\0');
        if (m_data_nsp->CopyData(offset, ident_command.cmdsize,
                                 result.data()) == ident_command.cmdsize) {
          LLDB_LOGF(log, "LC_IDENT found with text '%s'", result.c_str());
          return result;
        }
      }
      offset = cmd_offset + ident_command.cmdsize;
    }
  }
  return {};
}

AddressableBits ObjectFileMachO::GetAddressableBits() {
  AddressableBits addressable_bits;

  Log *log(GetLog(LLDBLog::Process));
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    auto lc_notes = FindLC_NOTEByName("addrable bits");
    for (auto lc_note : lc_notes) {
      offset_t payload_offset = std::get<0>(lc_note);
      uint32_t version;
      if (m_data_nsp->GetU32(&payload_offset, &version, 1) != nullptr) {
        if (version == 3) {
          uint32_t num_addr_bits =
              m_data_nsp->GetU32_unchecked(&payload_offset);
          addressable_bits.SetAddressableBits(num_addr_bits);
          LLDB_LOGF(log,
                    "LC_NOTE 'addrable bits' v3 found, value %d "
                    "bits",
                    num_addr_bits);
        }
        if (version == 4) {
          uint32_t lo_addr_bits = m_data_nsp->GetU32_unchecked(&payload_offset);
          uint32_t hi_addr_bits = m_data_nsp->GetU32_unchecked(&payload_offset);

          if (lo_addr_bits == hi_addr_bits)
            addressable_bits.SetAddressableBits(lo_addr_bits);
          else
            addressable_bits.SetAddressableBits(lo_addr_bits, hi_addr_bits);
          LLDB_LOGF(log, "LC_NOTE 'addrable bits' v4 found, value %d & %d bits",
                    lo_addr_bits, hi_addr_bits);
        }
      }
    }
  }
  return addressable_bits;
}

bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value,
                                                bool &value_is_offset,
                                                UUID &uuid,
                                                ObjectFile::BinaryType &type) {
  Log *log(
      GetLog(LLDBLog::Symbols | LLDBLog::Process | LLDBLog::DynamicLoader));
  value = LLDB_INVALID_ADDRESS;
  value_is_offset = false;
  uuid.Clear();
  uint32_t log2_pagesize = 0; // not currently passed up to caller
  uint32_t platform = 0;      // not currently passed up to caller
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

    auto lc_notes = FindLC_NOTEByName("main bin spec");
    for (auto lc_note : lc_notes) {
      offset_t payload_offset = std::get<0>(lc_note);

      // struct main_bin_spec
      // {
      //     uint32_t version;       // currently 2
      //     uint32_t type;          // 0 == unspecified,
      //                             // 1 == kernel
      //                             // 2 == user process,
      //                                     dyld mach-o binary addr
      //                             // 3 == standalone binary
      //                             // 4 == user process,
      //                             //      dyld_all_image_infos addr
      //     uint64_t address;       // UINT64_MAX if address not specified
      //     uint64_t slide;         // slide, UINT64_MAX if unspecified
      //                             // 0 if no slide needs to be applied to
      //                             // file address
      //     uuid_t   uuid;          // all zero's if uuid not specified
      //     uint32_t log2_pagesize; // process page size in log base 2,
      //                             // e.g. 4k pages are 12.
      //                             // 0 for unspecified
      //     uint32_t platform;      // The Mach-O platform for this corefile.
      //                             // 0 for unspecified.
      //                             // The values are defined in
      //                             // <mach-o/loader.h>, PLATFORM_*.
      // } __attribute((packed));

      // "main bin spec" (main binary specification) data payload is
      // formatted:
      //    uint32_t version       [currently 1]
      //    uint32_t type          [0 == unspecified, 1 == kernel,
      //                            2 == user process, 3 == firmware ]
      //    uint64_t address       [ UINT64_MAX if address not specified ]
      //    uuid_t   uuid          [ all zero's if uuid not specified ]
      //    uint32_t log2_pagesize [ process page size in log base
      //                             2, e.g. 4k pages are 12.
      //                             0 for unspecified ]
      //    uint32_t unused        [ for alignment ]

      uint32_t version;
      if (m_data_nsp->GetU32(&payload_offset, &version, 1) != nullptr &&
          version <= 2) {
        uint32_t binspec_type = 0;
        uuid_t raw_uuid;
        memset(raw_uuid, 0, sizeof(uuid_t));

        if (!m_data_nsp->GetU32(&payload_offset, &binspec_type, 1))
          return false;
        if (!m_data_nsp->GetU64(&payload_offset, &value, 1))
          return false;
        uint64_t slide = LLDB_INVALID_ADDRESS;
        if (version > 1 && !m_data_nsp->GetU64(&payload_offset, &slide, 1))
          return false;
        if (value == LLDB_INVALID_ADDRESS && slide != LLDB_INVALID_ADDRESS) {
          value = slide;
          value_is_offset = true;
        }

        if (m_data_nsp->CopyData(payload_offset, sizeof(uuid_t), raw_uuid) !=
            0) {
          uuid = UUID(raw_uuid, sizeof(uuid_t));
          // convert the "main bin spec" type into our
          // ObjectFile::BinaryType enum
          const char *typestr = "unrecognized type";
          type = eBinaryTypeInvalid;
          switch (binspec_type) {
          case 0:
            type = eBinaryTypeUnknown;
            typestr = "uknown";
            break;
          case 1:
            type = eBinaryTypeKernel;
            typestr = "xnu kernel";
            break;
          case 2:
            type = eBinaryTypeUser;
            typestr = "userland dyld";
            break;
          case 3:
            type = eBinaryTypeStandalone;
            typestr = "standalone";
            break;
          case 4:
            type = eBinaryTypeUserAllImageInfos;
            typestr = "userland dyld_all_image_infos";
            break;
          }
          LLDB_LOGF(log,
                    "LC_NOTE 'main bin spec' found, version %d type %d "
                    "(%s), value 0x%" PRIx64 " value-is-slide==%s uuid %s",
                    version, type, typestr, value,
                    value_is_offset ? "true" : "false",
                    uuid.GetAsString().c_str());
          if (!m_data_nsp->GetU32(&payload_offset, &log2_pagesize, 1))
            return false;
          if (version > 1 && !m_data_nsp->GetU32(&payload_offset, &platform, 1))
            return false;
          return true;
        }
      }
    }
  }
  return false;
}

bool ObjectFileMachO::GetCorefileThreadExtraInfos(
    std::vector<lldb::tid_t> &tids) {
  tids.clear();
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

    Log *log(GetLog(LLDBLog::Object | LLDBLog::Process | LLDBLog::Thread));
    if (StructuredData::ObjectSP object_sp = GetCorefileProcessMetadata()) {
      StructuredData::Dictionary *dict = object_sp->GetAsDictionary();
      StructuredData::Array *threads;
      if (!dict->GetValueForKeyAsArray("threads", threads) || !threads) {
        LLDB_LOGF(log,
                  "'process metadata' LC_NOTE does not have a 'threads' key");
        return false;
      }
      if (threads->GetSize() != GetNumThreadContexts()) {
        LLDB_LOGF(log, "Unable to read 'process metadata' LC_NOTE, number of "
                       "threads does not match number of LC_THREADS.");
        return false;
      }
      const size_t num_threads = threads->GetSize();
      for (size_t i = 0; i < num_threads; i++) {
        std::optional<StructuredData::Dictionary *> maybe_thread =
            threads->GetItemAtIndexAsDictionary(i);
        if (!maybe_thread) {
          LLDB_LOGF(log,
                    "Unable to read 'process metadata' LC_NOTE, threads "
                    "array does not have a dictionary at index %zu.",
                    i);
          return false;
        }
        StructuredData::Dictionary *thread = *maybe_thread;
        lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
        if (thread->GetValueForKeyAsInteger<lldb::tid_t>("thread_id", tid))
          if (tid == 0)
            tid = LLDB_INVALID_THREAD_ID;
        tids.push_back(tid);
      }

      if (log) {
        StreamString logmsg;
        logmsg.Printf("LC_NOTE 'process metadata' found: ");
        dict->Dump(logmsg, /* pretty_print */ false);
        LLDB_LOGF(log, "%s", logmsg.GetData());
      }
      return true;
    }
  }
  return false;
}

/// Return the payload of an LC_NOTE, decompressing it if needed.
///
/// A payload is either stored as is, or compressed in the layout of a GNU
/// .zdebug section:
///
///   offset  size  contents
///        0     4  magic "ZLIB"
///        4     8  uncompressed size, big-endian uint64_t
///       12     n  RFC 1950 zlib stream
///
/// The size is big-endian regardless of the corefile's byte order. An
/// uncompressed payload must not start with the magic.
static llvm::Expected<std::string> ReadLCNotePayload(const DataExtractor &data,
                                                     lldb::offset_t offset,
                                                     uint64_t size) {
  const uint8_t *bytes = data.PeekData(offset, size);
  if (!bytes)
    return llvm::createStringError(
        "payload of %" PRIu64 " bytes is out of bounds", size);
  llvm::ArrayRef<uint8_t> payload(bytes, size);

  constexpr llvm::StringLiteral magic = "ZLIB";
  constexpr size_t header_size = magic.size() + sizeof(uint64_t);
  if (!llvm::toStringRef(payload).starts_with(magic))
    return llvm::toStringRef(payload).str();
  if (payload.size() < header_size)
    return llvm::createStringError("compressed payload header is truncated");

  uint64_t uncompressed_size =
      llvm::support::endian::read64be(payload.data() + magic.size());
  llvm::ArrayRef<uint8_t> compressed = payload.drop_front(header_size);
  // Deflate cannot exceed a 1032:1 ratio. A larger claimed size is corrupt and
  // must not size the allocation.
  if (uncompressed_size / 1032 > compressed.size())
    return llvm::createStringError("uncompressed size %" PRIu64
                                   " is impossible for %zu compressed bytes",
                                   uncompressed_size, compressed.size());
  if (!llvm::compression::zlib::isAvailable())
    return llvm::createStringError(
        "payload is zlib-compressed but LLDB was built without zlib");

  llvm::SmallVector<uint8_t, 0> uncompressed;
  if (llvm::Error err = llvm::compression::zlib::decompress(
          compressed, uncompressed, uncompressed_size))
    return err;
  return llvm::toStringRef(uncompressed).str();
}

StructuredData::ObjectSP ObjectFileMachO::GetCorefileProcessMetadata() {
  ModuleSP module_sp(GetModule());
  if (!module_sp)
    return {};

  Log *log(GetLog(LLDBLog::Object | LLDBLog::Process | LLDBLog::Thread));
  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
  auto lc_notes = FindLC_NOTEByName("process metadata");
  if (lc_notes.size() == 0)
    return {};

  if (lc_notes.size() > 1)
    LLDB_LOGF(
        log,
        "Multiple 'process metadata' LC_NOTEs found, only using the first.");

  auto [payload_offset, payload_size] = lc_notes[0];
  llvm::Expected<std::string> json =
      ReadLCNotePayload(*m_data_nsp, payload_offset, payload_size);
  if (!json) {
    LLDB_LOG_ERROR(log, json.takeError(),
                   "Unable to read 'process metadata' LC_NOTE: {0}");
    return {};
  }
  StructuredData::ObjectSP object_sp =
      StructuredData::ParseJSON(llvm::StringRef(*json).rtrim('\0'));
  if (!object_sp) {
    LLDB_LOGF(log, "Unable to read 'process metadata' LC_NOTE, did not "
                   "parse as valid JSON.");
    return {};
  }
  StructuredData::Dictionary *dict = object_sp->GetAsDictionary();
  if (!dict) {
    LLDB_LOGF(log, "Unable to read 'process metadata' LC_NOTE, did not "
                   "get a dictionary.");
    return {};
  }

  return object_sp;
}

lldb::RegisterContextSP
ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx,
                                         lldb_private::Thread &thread) {
  lldb::RegisterContextSP reg_ctx_sp;

  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    if (!m_thread_context_offsets_valid)
      GetNumThreadContexts();

    const FileRangeArray::Entry *thread_context_file_range =
        m_thread_context_offsets.GetEntryAtIndex(idx);
    if (thread_context_file_range) {

      DataExtractor data(*m_data_nsp, thread_context_file_range->GetRangeBase(),
                         thread_context_file_range->GetByteSize());

      switch (m_header.cputype) {
      case llvm::MachO::CPU_TYPE_ARM64:
      case llvm::MachO::CPU_TYPE_ARM64_32:
        reg_ctx_sp =
            std::make_shared<RegisterContextDarwin_arm64_Mach>(thread, data);
        break;

      case llvm::MachO::CPU_TYPE_ARM:
        reg_ctx_sp =
            std::make_shared<RegisterContextDarwin_arm_Mach>(thread, data);
        break;

      case llvm::MachO::CPU_TYPE_X86_64:
        reg_ctx_sp =
            std::make_shared<RegisterContextDarwin_x86_64_Mach>(thread, data);
        break;

      case llvm::MachO::CPU_TYPE_RISCV:
        reg_ctx_sp =
            std::make_shared<RegisterContextDarwin_riscv32_Mach>(thread, data);
        break;
      }
    }
  }
  return reg_ctx_sp;
}

ObjectFile::Type ObjectFileMachO::CalculateType() {
  switch (m_header.filetype) {
  case MH_OBJECT: // 0x1u
    if (GetAddressByteSize() == 4) {
      // 32 bit kexts are just object files, but they do have a valid
      // UUID load command.
      if (GetUUID()) {
        // this checking for the UUID load command is not enough we could
        // eventually look for the symbol named "OSKextGetCurrentIdentifier" as
        // this is required of kexts
        if (m_strata == eStrataInvalid)
          m_strata = eStrataKernel;
        return eTypeSharedLibrary;
      }
    }
    return eTypeObjectFile;

  case MH_EXECUTE:
    return eTypeExecutable; // 0x2u
  case MH_FVMLIB:
    return eTypeSharedLibrary; // 0x3u
  case MH_CORE:
    return eTypeCoreFile; // 0x4u
  case MH_PRELOAD:
    return eTypeSharedLibrary; // 0x5u
  case MH_DYLIB:
    return eTypeSharedLibrary; // 0x6u
  case MH_DYLINKER:
    return eTypeDynamicLinker; // 0x7u
  case MH_BUNDLE:
    return eTypeSharedLibrary; // 0x8u
  case MH_DYLIB_STUB:
    return eTypeStubLibrary; // 0x9u
  case MH_DSYM:
    return eTypeDebugInfo; // 0xAu
  case MH_KEXT_BUNDLE:
    return eTypeSharedLibrary; // 0xBu
  default:
    break;
  }
  return eTypeUnknown;
}

ObjectFile::Strata ObjectFileMachO::CalculateStrata() {
  switch (m_header.filetype) {
  case MH_OBJECT: // 0x1u
  {
    // 32 bit kexts are just object files, but they do have a valid
    // UUID load command.
    if (GetUUID()) {
      // this checking for the UUID load command is not enough we could
      // eventually look for the symbol named "OSKextGetCurrentIdentifier" as
      // this is required of kexts
      if (m_type == eTypeInvalid)
        m_type = eTypeSharedLibrary;

      return eStrataKernel;
    }
  }
    return eStrataUnknown;

  case MH_EXECUTE: // 0x2u
    // Check for the MH_DYLDLINK bit in the flags
    if (m_header.flags & MH_DYLDLINK) {
      return eStrataUser;
    } else {
      SectionList *section_list = GetSectionList();
      if (section_list) {
        if (section_list->FindSectionByName("__KLD"))
          return eStrataKernel;
      }
    }
    return eStrataRawImage;

  case MH_FVMLIB:
    return eStrataUser; // 0x3u
  case MH_CORE:
    return eStrataUnknown; // 0x4u
  case MH_PRELOAD:
    return eStrataRawImage; // 0x5u
  case MH_DYLIB:
    return eStrataUser; // 0x6u
  case MH_DYLINKER:
    return eStrataUser; // 0x7u
  case MH_BUNDLE:
    return eStrataUser; // 0x8u
  case MH_DYLIB_STUB:
    return eStrataUser; // 0x9u
  case MH_DSYM:
    return eStrataUnknown; // 0xAu
  case MH_KEXT_BUNDLE:
    return eStrataKernel; // 0xBu
  default:
    break;
  }
  return eStrataUnknown;
}

llvm::VersionTuple ObjectFileMachO::GetVersion() {
  ModuleSP module_sp(GetModule());
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
    llvm::MachO::dylib_command load_cmd;
    lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
    uint32_t version_cmd = 0;
    uint64_t version = 0;
    uint32_t i;
    for (i = 0; i < m_header.ncmds; ++i) {
      const lldb::offset_t cmd_offset = offset;
      if (!ReadMachOCommand(*m_data_nsp, offset, load_cmd))
        break;

      if (load_cmd.cmd == LC_ID_DYLIB) {
        if (version_cmd == 0) {
          version_cmd = load_cmd.cmd;
          if (m_data_nsp->GetU32(&offset, &load_cmd.dylib, 4) == nullptr)
            break;
          version = load_cmd.dylib.current_version;
        }
        break; // Break for now unless there is another more complete version
               // number load command in the future.
      }
      offset = cmd_offset + load_cmd.cmdsize;
    }

    if (version_cmd == LC_ID_DYLIB) {
      unsigned major = (version & 0xFFFF0000ull) >> 16;
      unsigned minor = (version & 0x0000FF00ull) >> 8;
      unsigned subminor = (version & 0x000000FFull);
      return llvm::VersionTuple(major, minor, subminor);
    }
  }
  return llvm::VersionTuple();
}

ArchSpec ObjectFileMachO::GetArchitecture() {
  ModuleSP module_sp(GetModule());
  ArchSpec arch;
  if (module_sp) {
    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

    return GetArchitecture(module_sp, m_header, *m_data_nsp,
                           MachHeaderSizeFromMagic(m_header.magic));
  }
  return arch;
}

void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process,
                                                addr_t &base_addr, UUID &uuid) {
  uuid.Clear();
  base_addr = LLDB_INVALID_ADDRESS;
  if (process && process->GetDynamicLoader()) {
    DynamicLoader *dl = process->GetDynamicLoader();
    LazyBool using_shared_cache;
    LazyBool private_shared_cache;
    FileSpec sc_filepath;
    std::optional<uint64_t> size;
    dl->GetSharedCacheInformation(base_addr, uuid, using_shared_cache,
                                  private_shared_cache, sc_filepath, size);
  }
  Log *log(GetLog(LLDBLog::Symbols | LLDBLog::Process));
  LLDB_LOGF(
      log,
      "inferior process shared cache has a UUID of %s, base address 0x%" PRIx64,
      uuid.GetAsString().c_str(), base_addr);
}

// From dyld SPI header dyld_process_info.h
typedef void *dyld_process_info;
struct lldb_copy__dyld_process_cache_info {
  uuid_t cacheUUID;          // UUID of cache used by process
  uint64_t cacheBaseAddress; // load address of dyld shared cache
  bool noCache;              // process is running without a dyld cache
  bool privateCache; // process is using a private copy of its dyld cache
};

// #including mach/mach.h pulls in machine.h & CPU_TYPE_ARM etc conflicts with
// llvm enum definitions llvm::MachO::CPU_TYPE_ARM turning them into compile
// errors. So we need to use the actual underlying types of task_t and
// kern_return_t below.
extern "C" unsigned int /*task_t*/ mach_task_self();

void ObjectFileMachO::GetLLDBSharedCacheUUID(addr_t &base_addr, UUID &uuid) {
  uuid.Clear();
  base_addr = LLDB_INVALID_ADDRESS;

#if defined(__APPLE__)
  uint8_t *(*dyld_get_all_image_infos)(void);
  dyld_get_all_image_infos =
      (uint8_t * (*)()) dlsym(RTLD_DEFAULT, "_dyld_get_all_image_infos");
  if (dyld_get_all_image_infos) {
    uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos();
    if (dyld_all_image_infos_address) {
      uint32_t *version = (uint32_t *)
          dyld_all_image_infos_address; // version <mach-o/dyld_images.h>
      if (*version >= 13) {
        uuid_t *sharedCacheUUID_address = 0;
        int wordsize = sizeof(uint8_t *);
        if (wordsize == 8) {
          sharedCacheUUID_address =
              (uuid_t *)((uint8_t *)dyld_all_image_infos_address +
                         160); // sharedCacheUUID <mach-o/dyld_images.h>
          if (*version >= 15)
            base_addr =
                *(uint64_t
                      *)((uint8_t *)dyld_all_image_infos_address +
                         176); // sharedCacheBaseAddress <mach-o/dyld_images.h>
        } else {
          sharedCacheUUID_address =
              (uuid_t *)((uint8_t *)dyld_all_image_infos_address +
                         84); // sharedCacheUUID <mach-o/dyld_images.h>
          if (*version >= 15) {
            base_addr = 0;
            base_addr =
                *(uint32_t
                      *)((uint8_t *)dyld_all_image_infos_address +
                         100); // sharedCacheBaseAddress <mach-o/dyld_images.h>
          }
        }
        uuid = UUID(sharedCacheUUID_address, sizeof(uuid_t));
      }
    }
  } else {
    // Exists in macOS 10.12 and later, iOS 10.0 and later - dyld SPI
    dyld_process_info (*dyld_process_info_create)(
        unsigned int /* task_t */ task, uint64_t timestamp,
        unsigned int /*kern_return_t*/ *kernelError);
    void (*dyld_process_info_get_cache)(void *info, void *cacheInfo);
    void (*dyld_process_info_release)(dyld_process_info info);

    dyld_process_info_create = (void *(*)(unsigned int /* task_t */, uint64_t,
                                          unsigned int /*kern_return_t*/ *))
        dlsym(RTLD_DEFAULT, "_dyld_process_info_create");
    dyld_process_info_get_cache = (void (*)(void *, void *))dlsym(
        RTLD_DEFAULT, "_dyld_process_info_get_cache");
    dyld_process_info_release =
        (void (*)(void *))dlsym(RTLD_DEFAULT, "_dyld_process_info_release");

    if (dyld_process_info_create && dyld_process_info_get_cache) {
      unsigned int /*kern_return_t */ kern_ret;
      dyld_process_info process_info =
          dyld_process_info_create(::mach_task_self(), 0, &kern_ret);
      if (process_info) {
        struct lldb_copy__dyld_process_cache_info sc_info;
        memset(&sc_info, 0, sizeof(struct lldb_copy__dyld_process_cache_info));
        dyld_process_info_get_cache(process_info, &sc_info);
        if (sc_info.cacheBaseAddress != 0) {
          base_addr = sc_info.cacheBaseAddress;
          uuid = UUID(sc_info.cacheUUID, sizeof(uuid_t));
        }
        dyld_process_info_release(process_info);
      }
    }
  }
  Log *log(GetLog(LLDBLog::Symbols | LLDBLog::Process));
  if (log && uuid.IsValid())
    LLDB_LOGF(log,
              "lldb's in-memory shared cache has a UUID of %s base address of "
              "0x%" PRIx64,
              uuid.GetAsString().c_str(), base_addr);
#endif
}

static llvm::VersionTuple FindMinimumVersionInfo(DataExtractor &data,
                                                 lldb::offset_t offset,
                                                 size_t ncmds) {
  for (size_t i = 0; i < ncmds; i++) {
    const lldb::offset_t load_cmd_offset = offset;
    llvm::MachO::load_command lc = {};
    if (!ReadMachOCommand(data, offset, lc))
      break;

    uint32_t version = 0;
    if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX ||
        lc.cmd == llvm::MachO::LC_VERSION_MIN_IPHONEOS ||
        lc.cmd == llvm::MachO::LC_VERSION_MIN_TVOS ||
        lc.cmd == llvm::MachO::LC_VERSION_MIN_WATCHOS) {
      // struct version_min_command {
      //   uint32_t cmd; // LC_VERSION_MIN_*
      //   uint32_t cmdsize;
      //   uint32_t version; // X.Y.Z encoded in nibbles xxxx.yy.zz
      //   uint32_t sdk;
      // };
      // We want to read version.
      version = data.GetU32(&offset);
    } else if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
      // struct build_version_command {
      //   uint32_t cmd; // LC_BUILD_VERSION
      //   uint32_t cmdsize;
      //   uint32_t platform;
      //   uint32_t minos; // X.Y.Z encoded in nibbles xxxx.yy.zz
      //   uint32_t sdk;
      //   uint32_t ntools;
      // };
      // We want to read minos.
      offset += sizeof(uint32_t);     // Skip over platform
      version = data.GetU32(&offset); // Extract minos
    }

    if (version) {
      const uint32_t xxxx = version >> 16;
      const uint32_t yy = (version >> 8) & 0xffu;
      const uint32_t zz = version & 0xffu;
      if (xxxx)
        return llvm::VersionTuple(xxxx, yy, zz);
    }
    offset = load_cmd_offset + lc.cmdsize;
  }
  return llvm::VersionTuple();
}

llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() {
  if (!m_min_os_version)
    m_min_os_version = FindMinimumVersionInfo(
        *m_data_nsp, MachHeaderSizeFromMagic(m_header.magic), m_header.ncmds);
  return *m_min_os_version;
}

llvm::VersionTuple ObjectFileMachO::GetSDKVersion() {
  if (!m_sdk_versions)
    m_sdk_versions = FindMinimumVersionInfo(
        *m_data_nsp, MachHeaderSizeFromMagic(m_header.magic), m_header.ncmds);
  return *m_sdk_versions;
}

bool ObjectFileMachO::GetIsDynamicLinkEditor() {
  return m_header.filetype == llvm::MachO::MH_DYLINKER;
}

bool ObjectFileMachO::CanTrustAddressRanges() {
  // Dsymutil guarantees that the .debug_aranges accelerator is complete and can
  // be trusted by LLDB.
  return m_header.filetype == llvm::MachO::MH_DSYM;
}

bool ObjectFileMachO::AllowAssemblyEmulationUnwindPlans() {
  return m_allow_assembly_emulation_unwind_plans;
}

Section *ObjectFileMachO::GetMachHeaderSection() {
  // Find the first address of the mach header which is the first non-zero file
  // sized section whose file offset is zero. This is the base file address of
  // the mach-o file which can be subtracted from the vmaddr of the other
  // segments found in memory and added to the load address
  ModuleSP module_sp = GetModule();
  if (!module_sp)
    return nullptr;
  SectionList *section_list = GetSectionList();
  if (!section_list)
    return nullptr;

  // Some binaries can have a TEXT segment with a non-zero file offset.
  // Binaries in the shared cache are one example.  Some hand-generated
  // binaries may not be laid out in the normal TEXT,DATA,LC_SYMTAB order
  // in the file, even though they're laid out correctly in vmaddr terms.
  SectionSP text_segment_sp =
      section_list->FindSectionByName(GetSegmentNameTEXT());
  if (text_segment_sp.get() && SectionIsLoadable(text_segment_sp.get()))
    return text_segment_sp.get();

  const size_t num_sections = section_list->GetSize();
  for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
    Section *section = section_list->GetSectionAtIndex(sect_idx).get();
    if (section->GetFileOffset() == 0 && SectionIsLoadable(section))
      return section;
  }

  return nullptr;
}

bool ObjectFileMachO::IsGOTSection(const lldb_private::Section &section) const {
  assert(section.GetObjectFile() == this && "Wrong object file!");
  SectionSP segment = section.GetParent();
  if (!segment)
    return false;

  const bool is_data_const_got =
      segment->GetName() == "__DATA_CONST" && section.GetName() == "__got";
  const bool is_auth_const_ptr =
      segment->GetName() == "__AUTH_CONST" &&
      (section.GetName() == "__auth_got" || section.GetName() == "__auth_ptr");
  return is_data_const_got || is_auth_const_ptr;
}

bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
  if (!section)
    return false;
  if (section->IsThreadSpecific())
    return false;
  if (GetModule().get() != section->GetModule().get())
    return false;
  // firmware style binaries with llvm gcov segment do
  // not have that segment mapped into memory.
  if (section->GetName() == GetSegmentNameLLVM_COV()) {
    const Strata strata = GetStrata();
    if (strata == eStrataKernel || strata == eStrataRawImage)
      return false;
  }
  // Be careful with __LINKEDIT and __DWARF segments
  if (section->GetName() == GetSegmentNameLINKEDIT() ||
      section->GetName() == GetSegmentNameDWARF()) {
    // Only map __LINKEDIT and __DWARF if we have an in memory image and
    // this isn't a kernel binary like a kext or mach_kernel.
    const bool is_memory_image = (bool)m_process_wp.lock();
    const Strata strata = GetStrata();
    if (is_memory_image == false || strata == eStrataKernel)
      return false;
  }
  return true;
}

lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(
    lldb::addr_t header_load_address, const Section *header_section,
    const Section *section) {
  ModuleSP module_sp = GetModule();
  if (module_sp && header_section && section &&
      header_load_address != LLDB_INVALID_ADDRESS) {
    lldb::addr_t file_addr = header_section->GetFileAddress();
    if (file_addr != LLDB_INVALID_ADDRESS && SectionIsLoadable(section))
      return section->GetFileAddress() - file_addr + header_load_address;
  }
  return LLDB_INVALID_ADDRESS;
}

bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
                                     bool value_is_offset) {
  Log *log(GetLog(LLDBLog::DynamicLoader));
  ModuleSP module_sp = GetModule();
  if (!module_sp)
    return false;

  SectionList *section_list = GetSectionList();
  if (!section_list)
    return false;

  size_t num_loaded_sections = 0;
  const size_t num_sections = section_list->GetSize();

  // Warn if some top-level segments map to the same address. The binary may be
  // malformed.
  const bool warn_multiple = true;

  if (log) {
    StreamString logmsg;
    logmsg << "ObjectFileMachO::SetLoadAddress ";
    if (GetFileSpec())
      logmsg << "path='" << GetFileSpec().GetPath() << "' ";
    if (GetUUID()) {
      logmsg << "uuid=" << GetUUID().GetAsString();
    }
    LLDB_LOGF(log, "%s", logmsg.GetData());
  }
  if (value_is_offset) {
    // "value" is an offset to apply to each top level segment
    for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
      // Iterate through the object file sections to find all of the
      // sections that size on disk (to avoid __PAGEZERO) and load them
      SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
      if (SectionIsLoadable(section_sp.get())) {
        LLDB_LOG(
            log,
            "ObjectFileMachO::SetLoadAddress segment '{0}' load addr is {1:x}",
            section_sp->GetName(), section_sp->GetFileAddress() + value);
        if (target.SetSectionLoadAddress(section_sp,
                                         section_sp->GetFileAddress() + value,
                                         warn_multiple))
          ++num_loaded_sections;
      }
    }
  } else {
    // "value" is the new base address of the mach_header, adjust each
    // section accordingly

    Section *mach_header_section = GetMachHeaderSection();
    if (mach_header_section) {
      for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
        SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));

        lldb::addr_t section_load_addr =
            CalculateSectionLoadAddressForMemoryImage(
                value, mach_header_section, section_sp.get());
        if (section_load_addr != LLDB_INVALID_ADDRESS) {
          LLDB_LOG(log,
                   "ObjectFileMachO::SetLoadAddress segment '{0}' load addr is "
                   "{1:x}",
                   section_sp->GetName(), section_load_addr);
          if (target.SetSectionLoadAddress(section_sp, section_load_addr,
                                           warn_multiple))
            ++num_loaded_sections;
        }
      }
    }
  }
  return num_loaded_sections > 0;
}

struct all_image_infos_header {
  uint32_t version;         // currently 1
  uint32_t imgcount;        // number of binary images
  uint64_t entries_fileoff; // file offset in the corefile of where the array of
                            // struct entry's begin.
  uint32_t entries_size;    // size of 'struct entry'.
  uint32_t unused;
};

struct image_entry {
  uint64_t filepath_offset;  // offset in corefile to c-string of the file path,
                             // UINT64_MAX if unavailable.
  uuid_t uuid;               // uint8_t[16].  should be set to all zeroes if
                             // uuid is unknown.
  uint64_t load_address;     // UINT64_MAX if unknown.
  uint64_t seg_addrs_offset; // offset to the array of struct segment_vmaddr's.
  uint32_t segment_count;    // The number of segments for this binary.
  uint32_t unused;

  image_entry() {
    filepath_offset = UINT64_MAX;
    memset(&uuid, 0, sizeof(uuid_t));
    segment_count = 0;
    load_address = UINT64_MAX;
    seg_addrs_offset = UINT64_MAX;
    unused = 0;
  }
  image_entry(const image_entry &rhs) {
    filepath_offset = rhs.filepath_offset;
    memcpy(&uuid, &rhs.uuid, sizeof(uuid_t));
    segment_count = rhs.segment_count;
    seg_addrs_offset = rhs.seg_addrs_offset;
    load_address = rhs.load_address;
    unused = rhs.unused;
  }
};

struct segment_vmaddr {
  char segname[16];
  uint64_t vmaddr;
  uint64_t unused;

  segment_vmaddr() {
    memset(&segname, 0, 16);
    vmaddr = UINT64_MAX;
    unused = 0;
  }
  segment_vmaddr(const segment_vmaddr &rhs) {
    memcpy(&segname, &rhs.segname, 16);
    vmaddr = rhs.vmaddr;
    unused = rhs.unused;
  }
};

// Write the payload for the "all image infos" LC_NOTE into
// the supplied all_image_infos_payload, assuming that this
// will be written into the corefile starting at
// initial_file_offset.
//
// The placement of this payload is a little tricky.  We're
// laying this out as
//
// 1. header (struct all_image_info_header)
// 2. Array of fixed-size (struct image_entry)'s, one
//    per binary image present in the process.
// 3. Arrays of (struct segment_vmaddr)'s, a varying number
//    for each binary image.
// 4. Variable length c-strings of binary image filepaths,
//    one per binary.
//
// To compute where everything will be laid out in the
// payload, we need to iterate over the images and calculate
// how many segment_vmaddr structures each image will need,
// and how long each image's filepath c-string is. There
// are some multiple passes over the image list while calculating
// everything.

static offset_t
CreateAllImageInfosPayload(const lldb::ProcessSP &process_sp,
                           offset_t initial_file_offset,
                           StreamString &all_image_infos_payload,
                           lldb_private::SaveCoreOptions &options) {
  Target &target = process_sp->GetTarget();
  ModuleList modules = target.GetImages();

  // stack-only corefiles have no reason to include binaries that
  // are not executing; we're trying to make the smallest corefile
  // we can, so leave the rest out.
  if (options.GetStyle() == SaveCoreStyle::eSaveCoreStackOnly)
    modules.Clear();

  std::set<std::string> executing_uuids;
  std::vector<ThreadSP> thread_list =
      process_sp->CalculateCoreFileThreadList(options);
  for (const ThreadSP &thread_sp : thread_list) {
    uint32_t stack_frame_count = thread_sp->GetStackFrameCount();
    for (uint32_t j = 0; j < stack_frame_count; j++) {
      StackFrameSP stack_frame_sp = thread_sp->GetStackFrameAtIndex(j);
      Address pc = stack_frame_sp->GetFrameCodeAddress();
      ModuleSP module_sp = pc.GetModule();
      if (module_sp) {
        UUID uuid = module_sp->GetUUID();
        if (uuid.IsValid()) {
          executing_uuids.insert(uuid.GetAsString());
          modules.AppendIfNeeded(module_sp);
        }
      }
    }
  }
  size_t modules_count = modules.GetSize();

  struct all_image_infos_header infos;
  infos.version = 1;
  infos.imgcount = modules_count;
  infos.entries_size = sizeof(image_entry);
  infos.entries_fileoff = initial_file_offset + sizeof(all_image_infos_header);
  infos.unused = 0;

  all_image_infos_payload.PutHex32(infos.version);
  all_image_infos_payload.PutHex32(infos.imgcount);
  all_image_infos_payload.PutHex64(infos.entries_fileoff);
  all_image_infos_payload.PutHex32(infos.entries_size);
  all_image_infos_payload.PutHex32(infos.unused);

  // First create the structures for all of the segment name+vmaddr vectors
  // for each module, so we will know the size of them as we add the
  // module entries.
  std::vector<std::vector<segment_vmaddr>> modules_segment_vmaddrs;
  for (size_t i = 0; i < modules_count; i++) {
    ModuleSP module = modules.GetModuleAtIndex(i);

    SectionList *sections = module->GetSectionList();
    size_t sections_count = sections->GetSize();
    std::vector<segment_vmaddr> segment_vmaddrs;
    for (size_t j = 0; j < sections_count; j++) {
      SectionSP section = sections->GetSectionAtIndex(j);
      if (!section->GetParent().get()) {
        addr_t vmaddr = section->GetLoadBaseAddress(&target);
        if (vmaddr == LLDB_INVALID_ADDRESS)
          continue;
        llvm::StringRef name = section->GetName();
        segment_vmaddr seg_vmaddr;
        // This is the uncommon case where strncpy is exactly
        // the right one, doesn't need to be null-terminated.
        // The segment name in a Mach-O LC_SEGMENT/LC_SEGMENT_64 is char[16] and
        // is not guaranteed to be null-terminated if all 16 characters are
        // used.
        // coverity[buffer_size_warning]
        strncpy(seg_vmaddr.segname, name.data(),
                std::min(name.size(), sizeof(seg_vmaddr.segname)));
        seg_vmaddr.vmaddr = vmaddr;
        seg_vmaddr.unused = 0;
        segment_vmaddrs.push_back(seg_vmaddr);
      }
    }
    modules_segment_vmaddrs.push_back(segment_vmaddrs);
  }

  offset_t size_of_vmaddr_structs = 0;
  for (size_t i = 0; i < modules_segment_vmaddrs.size(); i++) {
    size_of_vmaddr_structs +=
        modules_segment_vmaddrs[i].size() * sizeof(segment_vmaddr);
  }

  offset_t size_of_filepath_cstrings = 0;
  for (size_t i = 0; i < modules_count; i++) {
    ModuleSP module_sp = modules.GetModuleAtIndex(i);
    size_of_filepath_cstrings += module_sp->GetFileSpec().GetPath().size() + 1;
  }

  // Calculate the file offsets of our "all image infos" payload in the
  // corefile. initial_file_offset the original value passed in to this method.

  offset_t start_of_entries =
      initial_file_offset + sizeof(all_image_infos_header);
  offset_t start_of_seg_vmaddrs =
      start_of_entries + sizeof(image_entry) * modules_count;
  offset_t start_of_filenames = start_of_seg_vmaddrs + size_of_vmaddr_structs;

  offset_t final_file_offset = start_of_filenames + size_of_filepath_cstrings;

  // Now write the one-per-module 'struct image_entry' into the
  // StringStream; keep track of where the struct segment_vmaddr
  // entries for each module will end up in the corefile.

  offset_t current_string_offset = start_of_filenames;
  offset_t current_segaddrs_offset = start_of_seg_vmaddrs;
  for (size_t i = 0; i < modules_count; i++) {
    ModuleSP module_sp = modules.GetModuleAtIndex(i);

    struct image_entry ent;
    memcpy(&ent.uuid, module_sp->GetUUID().GetBytes().data(), sizeof(ent.uuid));
    if (modules_segment_vmaddrs[i].size() > 0) {
      ent.segment_count = modules_segment_vmaddrs[i].size();
      ent.seg_addrs_offset = current_segaddrs_offset;
    }
    ent.filepath_offset = current_string_offset;
    ObjectFile *objfile = module_sp->GetObjectFile();
    if (objfile) {
      Address base_addr(objfile->GetBaseAddress());
      if (base_addr.IsValid()) {
        ent.load_address = base_addr.GetLoadAddress(&target);
      }
    }

    all_image_infos_payload.PutHex64(ent.filepath_offset);
    all_image_infos_payload.PutRawBytes(ent.uuid, sizeof(ent.uuid));
    all_image_infos_payload.PutHex64(ent.load_address);
    all_image_infos_payload.PutHex64(ent.seg_addrs_offset);
    all_image_infos_payload.PutHex32(ent.segment_count);

    if (executing_uuids.find(module_sp->GetUUID().GetAsString()) !=
        executing_uuids.end())
      all_image_infos_payload.PutHex32(1);
    else
      all_image_infos_payload.PutHex32(0);

    current_segaddrs_offset += ent.segment_count * sizeof(segment_vmaddr);
    current_string_offset += module_sp->GetFileSpec().GetPath().size() + 1;
  }

  // Now write the struct segment_vmaddr entries into the StringStream.

  for (size_t i = 0; i < modules_segment_vmaddrs.size(); i++) {
    if (modules_segment_vmaddrs[i].size() == 0)
      continue;
    for (struct segment_vmaddr segvm : modules_segment_vmaddrs[i]) {
      all_image_infos_payload.PutRawBytes(segvm.segname, sizeof(segvm.segname));
      all_image_infos_payload.PutHex64(segvm.vmaddr);
      all_image_infos_payload.PutHex64(segvm.unused);
    }
  }

  for (size_t i = 0; i < modules_count; i++) {
    ModuleSP module_sp = modules.GetModuleAtIndex(i);
    std::string filepath = module_sp->GetFileSpec().GetPath();
    all_image_infos_payload.PutRawBytes(filepath.data(), filepath.size() + 1);
  }

  return final_file_offset;
}

// Temp struct used to combine contiguous memory regions with
// identical permissions.
struct page_object {
  addr_t addr;
  addr_t size;
  uint32_t prot;
};

bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
                               lldb_private::SaveCoreOptions &options,
                               Status &error) {
  // The FileSpec and Process are already checked in PluginManager::SaveCore.
  assert(options.GetOutputFile().has_value());
  assert(process_sp);
  const FileSpec outfile = options.GetOutputFile().value();

  // MachO defaults to dirty pages
  if (options.GetStyle() == SaveCoreStyle::eSaveCoreUnspecified)
    options.SetStyle(eSaveCoreDirtyOnly);

  Target &target = process_sp->GetTarget();
  const ArchSpec target_arch = target.GetArchitecture();
  const llvm::Triple &target_triple = target_arch.GetTriple();
  if (target_triple.getVendor() == llvm::Triple::Apple &&
      (target_triple.getOS() == llvm::Triple::MacOSX ||
       target_triple.getOS() == llvm::Triple::IOS ||
       target_triple.getOS() == llvm::Triple::WatchOS ||
       target_triple.getOS() == llvm::Triple::TvOS ||
       target_triple.getOS() == llvm::Triple::BridgeOS ||
       target_triple.getOS() == llvm::Triple::XROS)) {
    bool make_core = false;
    switch (target_arch.GetMachine()) {
    case llvm::Triple::aarch64:
    case llvm::Triple::aarch64_32:
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      make_core = true;
      break;
    default:
      error = Status::FromErrorStringWithFormat(
          "unsupported core architecture: %s", target_triple.str().c_str());
      break;
    }

    if (make_core) {
      CoreFileMemoryRanges core_ranges;
      error = process_sp->CalculateCoreFileSaveRanges(options, core_ranges);
      if (error.Success()) {
        const uint32_t addr_byte_size = target_arch.GetAddressByteSize();
        const ByteOrder byte_order = target_arch.GetByteOrder();
        std::vector<llvm::MachO::segment_command_64> segment_load_commands;
        for (const auto &core_range_info : core_ranges) {
          // TODO: Refactor RangeDataVector to have a data iterator.
          const auto &core_range = core_range_info.data;
          uint32_t cmd_type = LC_SEGMENT_64;
          uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
          if (addr_byte_size == 4) {
            cmd_type = LC_SEGMENT;
            segment_size = sizeof(llvm::MachO::segment_command);
          }
          // Skip any ranges with no read/write/execute permissions and empty
          // ranges.
          if (core_range.lldb_permissions == 0 || core_range.range.size() == 0)
            continue;
          uint32_t vm_prot = 0;
          if (core_range.lldb_permissions & ePermissionsReadable)
            vm_prot |= VM_PROT_READ;
          if (core_range.lldb_permissions & ePermissionsWritable)
            vm_prot |= VM_PROT_WRITE;
          if (core_range.lldb_permissions & ePermissionsExecutable)
            vm_prot |= VM_PROT_EXECUTE;
          const addr_t vm_addr = core_range.range.start();
          const addr_t vm_size = core_range.range.size();
          llvm::MachO::segment_command_64 segment = {
              cmd_type,     // uint32_t cmd;
              segment_size, // uint32_t cmdsize;
              {0},          // char segname[16];
              vm_addr,      // uint64_t vmaddr;   // uint32_t for 32-bit Mach-O
              vm_size,      // uint64_t vmsize;   // uint32_t for 32-bit Mach-O
              0,            // uint64_t fileoff;  // uint32_t for 32-bit Mach-O
              vm_size,      // uint64_t filesize; // uint32_t for 32-bit Mach-O
              vm_prot,      // uint32_t maxprot;
              vm_prot,      // uint32_t initprot;
              0,            // uint32_t nsects;
              0};           // uint32_t flags;
          segment_load_commands.push_back(segment);
        }

        StreamString buffer(Stream::eBinary, byte_order);

        llvm::MachO::mach_header_64 mach_header;
        mach_header.magic = addr_byte_size == 8 ? MH_MAGIC_64 : MH_MAGIC;
        mach_header.cputype = target_arch.GetMachOCPUType();
        mach_header.cpusubtype = target_arch.GetMachOCPUSubType();
        mach_header.filetype = MH_CORE;
        mach_header.ncmds = segment_load_commands.size();
        mach_header.flags = 0;
        mach_header.reserved = 0;
        ThreadList &thread_list = process_sp->GetThreadList();
        const uint32_t num_threads = thread_list.GetSize();

        // Make an array of LC_THREAD data items. Each one contains the
        // contents of the LC_THREAD load command. The data doesn't contain
        // the load command + load command size, we will add the load command
        // and load command size as we emit the data.
        std::vector<StreamString> LC_THREAD_datas(num_threads);
        for (auto &LC_THREAD_data : LC_THREAD_datas) {
          LC_THREAD_data.GetFlags().Set(Stream::eBinary);
          LC_THREAD_data.SetByteOrder(byte_order);
        }
        for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
          ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx));
          if (thread_sp) {
            switch (mach_header.cputype) {
            case llvm::MachO::CPU_TYPE_ARM64:
            case llvm::MachO::CPU_TYPE_ARM64_32:
              RegisterContextDarwin_arm64_Mach::Create_LC_THREAD(
                  thread_sp.get(), LC_THREAD_datas[thread_idx]);
              break;

            case llvm::MachO::CPU_TYPE_ARM:
              RegisterContextDarwin_arm_Mach::Create_LC_THREAD(
                  thread_sp.get(), LC_THREAD_datas[thread_idx]);
              break;

            case llvm::MachO::CPU_TYPE_X86_64:
              RegisterContextDarwin_x86_64_Mach::Create_LC_THREAD(
                  thread_sp.get(), LC_THREAD_datas[thread_idx]);
              break;

            case llvm::MachO::CPU_TYPE_RISCV:
              RegisterContextDarwin_riscv32_Mach::Create_LC_THREAD(
                  thread_sp.get(), LC_THREAD_datas[thread_idx]);
              break;
            }
          }
        }

        // The size of the load command is the size of the segments...
        if (addr_byte_size == 8) {
          mach_header.sizeofcmds = segment_load_commands.size() *
                                   sizeof(llvm::MachO::segment_command_64);
        } else {
          mach_header.sizeofcmds = segment_load_commands.size() *
                                   sizeof(llvm::MachO::segment_command);
        }

        // and the size of all LC_THREAD load command
        for (const auto &LC_THREAD_data : LC_THREAD_datas) {
          ++mach_header.ncmds;
          mach_header.sizeofcmds += 8 + LC_THREAD_data.GetSize();
        }

        // Bits will be set to indicate which bits are NOT used in
        // addressing in this process or 0 for unknown.
        uint64_t address_mask = process_sp->GetCodeAddressMask();
        if (address_mask != LLDB_INVALID_ADDRESS_MASK) {
          // LC_NOTE "addrable bits"
          mach_header.ncmds++;
          mach_header.sizeofcmds += sizeof(llvm::MachO::note_command);
        }

        // LC_NOTE "process metadata"
        mach_header.ncmds++;
        mach_header.sizeofcmds += sizeof(llvm::MachO::note_command);

        // LC_NOTE "all image infos"
        mach_header.ncmds++;
        mach_header.sizeofcmds += sizeof(llvm::MachO::note_command);

        // Write the mach header
        buffer.PutHex32(mach_header.magic);
        buffer.PutHex32(mach_header.cputype);
        buffer.PutHex32(mach_header.cpusubtype);
        buffer.PutHex32(mach_header.filetype);
        buffer.PutHex32(mach_header.ncmds);
        buffer.PutHex32(mach_header.sizeofcmds);
        buffer.PutHex32(mach_header.flags);
        if (addr_byte_size == 8) {
          buffer.PutHex32(mach_header.reserved);
        }

        // Skip the mach header and all load commands and align to the next
        // 0x1000 byte boundary
        addr_t file_offset = buffer.GetSize() + mach_header.sizeofcmds;

        file_offset = llvm::alignTo(file_offset, 16);
        std::vector<std::unique_ptr<LCNoteEntry>> lc_notes;

        // Add "addrable bits" LC_NOTE when an address mask is available
        if (address_mask != LLDB_INVALID_ADDRESS_MASK) {
          std::unique_ptr<LCNoteEntry> addrable_bits_lcnote_up(
              new LCNoteEntry(byte_order));
          addrable_bits_lcnote_up->name = "addrable bits";
          addrable_bits_lcnote_up->payload_file_offset = file_offset;
          int bits = std::bitset<64>(~address_mask).count();
          addrable_bits_lcnote_up->payload.PutHex32(4); // version
          addrable_bits_lcnote_up->payload.PutHex32(
              bits); // # of bits used for low addresses
          addrable_bits_lcnote_up->payload.PutHex32(
              bits); // # of bits used for high addresses
          addrable_bits_lcnote_up->payload.PutHex32(0); // reserved

          file_offset += addrable_bits_lcnote_up->payload.GetSize();

          lc_notes.push_back(std::move(addrable_bits_lcnote_up));
        }

        // Add "process metadata" LC_NOTE
        std::unique_ptr<LCNoteEntry> thread_extrainfo_lcnote_up(
            new LCNoteEntry(byte_order));
        thread_extrainfo_lcnote_up->name = "process metadata";
        thread_extrainfo_lcnote_up->payload_file_offset = file_offset;

        StructuredData::DictionarySP dict(
            std::make_shared<StructuredData::Dictionary>());
        StructuredData::ArraySP threads(
            std::make_shared<StructuredData::Array>());
        for (const ThreadSP &thread_sp :
             process_sp->CalculateCoreFileThreadList(options)) {
          StructuredData::DictionarySP thread(
              std::make_shared<StructuredData::Dictionary>());
          thread->AddIntegerItem("thread_id", thread_sp->GetID());
          threads->AddItem(thread);
        }
        dict->AddItem("threads", threads);
        StreamString strm;
        dict->Dump(strm, /* pretty */ false);
        thread_extrainfo_lcnote_up->payload.PutRawBytes(strm.GetData(),
                                                        strm.GetSize());

        file_offset += thread_extrainfo_lcnote_up->payload.GetSize();
        file_offset = llvm::alignTo(file_offset, 16);
        lc_notes.push_back(std::move(thread_extrainfo_lcnote_up));

        // Add "all image infos" LC_NOTE
        std::unique_ptr<LCNoteEntry> all_image_infos_lcnote_up(
            new LCNoteEntry(byte_order));
        all_image_infos_lcnote_up->name = "all image infos";
        all_image_infos_lcnote_up->payload_file_offset = file_offset;
        file_offset = CreateAllImageInfosPayload(
            process_sp, file_offset, all_image_infos_lcnote_up->payload,
            options);
        lc_notes.push_back(std::move(all_image_infos_lcnote_up));

        // Add LC_NOTE load commands
        for (auto &lcnote : lc_notes) {
          // Add the LC_NOTE load command to the file.
          buffer.PutHex32(LC_NOTE);
          buffer.PutHex32(sizeof(llvm::MachO::note_command));
          char namebuf[16];
          memset(namebuf, 0, sizeof(namebuf));
          // This is the uncommon case where strncpy is exactly
          // the right one, doesn't need to be null-terminated.
          // LC_NOTE name field is char[16] and is not guaranteed to be
          // null-terminated.
          // coverity[buffer_size_warning]
          strncpy(namebuf, lcnote->name.c_str(), sizeof(namebuf));
          buffer.PutRawBytes(namebuf, sizeof(namebuf));
          buffer.PutHex64(lcnote->payload_file_offset);
          buffer.PutHex64(lcnote->payload.GetSize());
        }

        // Align to 4096-byte page boundary for the LC_SEGMENTs.
        file_offset = llvm::alignTo(file_offset, 4096);

        for (auto &segment : segment_load_commands) {
          segment.fileoff = file_offset;
          file_offset += segment.filesize;
        }

        // Write out all of the LC_THREAD load commands
        for (const auto &LC_THREAD_data : LC_THREAD_datas) {
          const size_t LC_THREAD_data_size = LC_THREAD_data.GetSize();
          buffer.PutHex32(LC_THREAD);
          buffer.PutHex32(8 + LC_THREAD_data_size); // cmd + cmdsize + data
          buffer.Write(LC_THREAD_data.GetString().data(), LC_THREAD_data_size);
        }

        // Write out all of the segment load commands
        for (const auto &segment : segment_load_commands) {
          buffer.PutHex32(segment.cmd);
          buffer.PutHex32(segment.cmdsize);
          buffer.PutRawBytes(segment.segname, sizeof(segment.segname));
          if (addr_byte_size == 8) {
            buffer.PutHex64(segment.vmaddr);
            buffer.PutHex64(segment.vmsize);
            buffer.PutHex64(segment.fileoff);
            buffer.PutHex64(segment.filesize);
          } else {
            buffer.PutHex32(static_cast<uint32_t>(segment.vmaddr));
            buffer.PutHex32(static_cast<uint32_t>(segment.vmsize));
            buffer.PutHex32(static_cast<uint32_t>(segment.fileoff));
            buffer.PutHex32(static_cast<uint32_t>(segment.filesize));
          }
          buffer.PutHex32(segment.maxprot);
          buffer.PutHex32(segment.initprot);
          buffer.PutHex32(segment.nsects);
          buffer.PutHex32(segment.flags);
        }

        std::string core_file_path(outfile.GetPath());
        auto core_file = FileSystem::Instance().Open(
            outfile, File::eOpenOptionWriteOnly | File::eOpenOptionTruncate |
                         File::eOpenOptionCanCreate);
        if (!core_file) {
          error = Status::FromError(core_file.takeError());
        } else {
          // Read 1 page at a time
          uint8_t bytes[0x1000];
          // Write the mach header and load commands out to the core file
          size_t bytes_written = buffer.GetString().size();
          error =
              core_file.get()->Write(buffer.GetString().data(), bytes_written);
          if (error.Success()) {

            for (auto &lcnote : lc_notes) {
              if (core_file.get()->SeekFromStart(lcnote->payload_file_offset) ==
                  -1) {
                error = Status::FromErrorStringWithFormat(
                    "Unable to seek to corefile pos "
                    "to write '%s' LC_NOTE payload",
                    lcnote->name.c_str());
                return false;
              }
              bytes_written = lcnote->payload.GetSize();
              error = core_file.get()->Write(lcnote->payload.GetData(),
                                             bytes_written);
              if (!error.Success())
                return false;
            }

            // Now write the file data for all memory segments in the process
            for (const auto &segment : segment_load_commands) {
              if (core_file.get()->SeekFromStart(segment.fileoff) == -1) {
                error = Status::FromErrorStringWithFormat(
                    "unable to seek to offset 0x%" PRIx64 " in '%s'",
                    segment.fileoff, core_file_path.c_str());
                break;
              }

              target.GetDebugger().GetAsyncOutputStream()->Printf(
                  "Saving %" PRId64
                  " bytes of data for memory region at 0x%" PRIx64 "\n",
                  segment.vmsize, segment.vmaddr);
              addr_t bytes_left = segment.vmsize;
              addr_t addr = segment.vmaddr;
              Status memory_read_error;
              while (bytes_left > 0 && error.Success()) {
                const size_t bytes_to_read =
                    bytes_left > sizeof(bytes) ? sizeof(bytes) : bytes_left;

                // In a savecore setting, we don't really care about caching,
                // as the data is dumped and very likely never read again,
                // so we call ReadMemoryFromInferior to bypass it.
                const size_t bytes_read = process_sp->ReadMemoryFromInferior(
                    addr, bytes, bytes_to_read, memory_read_error);

                if (bytes_read == bytes_to_read) {
                  size_t bytes_written = bytes_read;
                  error = core_file.get()->Write(bytes, bytes_written);
                  bytes_left -= bytes_read;
                  addr += bytes_read;
                } else {
                  // Some pages within regions are not readable, those should
                  // be zero filled
                  memset(bytes, 0, bytes_to_read);
                  size_t bytes_written = bytes_to_read;
                  error = core_file.get()->Write(bytes, bytes_written);
                  bytes_left -= bytes_to_read;
                  addr += bytes_to_read;
                }
              }
            }
          }
        }
      }
    }
    return true; // This is the right plug to handle saving core files for
                 // this process
  }
  return false;
}

ObjectFileMachO::MachOCorefileAllImageInfos
ObjectFileMachO::GetCorefileAllImageInfos() {
  MachOCorefileAllImageInfos image_infos;
  Log *log(GetLog(LLDBLog::Object | LLDBLog::Symbols | LLDBLog::Process |
                  LLDBLog::DynamicLoader));

  auto lc_notes = FindLC_NOTEByName("all image infos");
  for (auto lc_note : lc_notes) {
    offset_t payload_offset = std::get<0>(lc_note);
    // Read the struct all_image_infos_header.
    uint32_t version = m_data_nsp->GetU32(&payload_offset);
    if (version != 1) {
      return image_infos;
    }
    uint32_t imgcount = m_data_nsp->GetU32(&payload_offset);
    uint64_t entries_fileoff = m_data_nsp->GetU64(&payload_offset);
    // 'entries_size' is not used, nor is the 'unused' entry.
    //  offset += 4; // uint32_t entries_size;
    //  offset += 4; // uint32_t unused;

    LLDB_LOGF(log, "LC_NOTE 'all image infos' found version %d with %d images",
              version, imgcount);
    payload_offset = entries_fileoff;
    for (uint32_t i = 0; i < imgcount; i++) {
      // Read the struct image_entry.
      offset_t filepath_offset = m_data_nsp->GetU64(&payload_offset);
      uuid_t uuid;
      memcpy(&uuid, m_data_nsp->GetData(&payload_offset, sizeof(uuid_t)),
             sizeof(uuid_t));
      uint64_t load_address = m_data_nsp->GetU64(&payload_offset);
      offset_t seg_addrs_offset = m_data_nsp->GetU64(&payload_offset);
      uint32_t segment_count = m_data_nsp->GetU32(&payload_offset);
      uint32_t currently_executing = m_data_nsp->GetU32(&payload_offset);

      MachOCorefileImageEntry image_entry;
      image_entry.filename =
          (const char *)m_data_nsp->GetCStr(&filepath_offset);
      image_entry.uuid = UUID(uuid, sizeof(uuid_t));
      image_entry.load_address = load_address;
      image_entry.currently_executing = currently_executing;

      offset_t seg_vmaddrs_offset = seg_addrs_offset;
      for (uint32_t j = 0; j < segment_count; j++) {
        char segname[17];
        m_data_nsp->CopyData(seg_vmaddrs_offset, 16, segname);
        segname[16] = '\0';
        seg_vmaddrs_offset += 16;
        uint64_t vmaddr = m_data_nsp->GetU64(&seg_vmaddrs_offset);
        seg_vmaddrs_offset += 8; /* unused */

        std::tuple<ConstString, addr_t> new_seg{ConstString(segname), vmaddr};
        image_entry.segment_load_addresses.push_back(new_seg);
      }
      LLDB_LOGF(log, "  image entry: %s %s 0x%" PRIx64 " %s",
                image_entry.filename.c_str(),
                image_entry.uuid.GetAsString().c_str(),
                image_entry.load_address,
                image_entry.currently_executing ? "currently executing"
                                                : "not currently executing");
      image_infos.all_image_infos.push_back(image_entry);
    }
  }

  lc_notes = FindLC_NOTEByName("load binary");
  for (auto lc_note : lc_notes) {
    offset_t payload_offset = std::get<0>(lc_note);
    uint32_t version = m_data_nsp->GetU32(&payload_offset);
    if (version == 1) {
      uuid_t uuid;
      memcpy(&uuid, m_data_nsp->GetData(&payload_offset, sizeof(uuid_t)),
             sizeof(uuid_t));
      uint64_t load_address = m_data_nsp->GetU64(&payload_offset);
      uint64_t slide = m_data_nsp->GetU64(&payload_offset);
      std::string filename = m_data_nsp->GetCStr(&payload_offset);

      MachOCorefileImageEntry image_entry;
      image_entry.filename = filename;
      image_entry.uuid = UUID(uuid, sizeof(uuid_t));
      image_entry.load_address = load_address;
      image_entry.slide = slide;
      image_entry.currently_executing = true;
      image_infos.all_image_infos.push_back(image_entry);
      LLDB_LOGF(log,
                "LC_NOTE 'load binary' found, filename %s uuid %s load "
                "address 0x%" PRIx64 " slide 0x%" PRIx64,
                filename.c_str(),
                image_entry.uuid.IsValid()
                    ? image_entry.uuid.GetAsString().c_str()
                    : "00000000-0000-0000-0000-000000000000",
                load_address, slide);
    }
  }

  return image_infos;
}

bool ObjectFileMachO::LoadCoreFileImages(lldb_private::Process &process) {
  MachOCorefileAllImageInfos image_infos = GetCorefileAllImageInfos();
  Log *log = GetLog(LLDBLog::Object | LLDBLog::DynamicLoader);

  bool found_platform_binary = false;
  ModuleList added_modules;

  llvm::SmallVector<const MachOCorefileImageEntry *> pending_images;
  std::vector<DynamicLoader::BinarySpec> pending_specs;

  for (MachOCorefileImageEntry &image : image_infos.all_image_infos) {
    // If this is a platform binary, it has been loaded (or registered with
    // the DynamicLoader to be loaded), we don't need to do any further
    // processing.  We're not going to call ModulesDidLoad on this in this
    // method, so notify==true.
    //
    // Setting up a platform binary can replace the Target's platform and
    // dynamic loader, so no image is searched for until this loop has run to
    // the end.
    if (process.GetTarget()
            .GetDebugger()
            .GetPlatformList()
            .LoadPlatformBinaryAndSetup(&process, image.load_address,
                                        true /* notify */)) {
      LLDB_LOGF(log,
                "ObjectFileMachO::%s binary at 0x%" PRIx64
                " is a platform binary, has been handled by a Platform plugin.",
                __FUNCTION__, image.load_address);
      found_platform_binary = true;
      continue;
    }

    bool value_is_offset = image.load_address == LLDB_INVALID_ADDRESS;
    uint64_t value = value_is_offset ? image.slide : image.load_address;
    if (value_is_offset && value == LLDB_INVALID_ADDRESS) {
      // We have neither address nor slide; so we will find the binary
      // by UUID and load it at slide/offset 0.
      value = 0;
    }

    // We have either a UUID, or we have a load address which
    // and can try to read load commands and find a UUID.
    if (!image.uuid.IsValid() &&
        (value_is_offset || value == LLDB_INVALID_ADDRESS))
      continue;

    DynamicLoader::BinarySpec bin_spec;
    bin_spec.name = image.filename;
    bin_spec.uuid = image.uuid;
    bin_spec.value = value;
    bin_spec.value_is_offset = value_is_offset;
    bin_spec.force_symbol_search = image.currently_executing;
    bin_spec.notify = false;
    // Userland Darwin binaries will have segment load addresses via
    // the `all image infos` LC_NOTE.
    bin_spec.set_address_in_target = image.segment_load_addresses.empty();
    bin_spec.allow_memory_image_last_resort =
        !image.segment_load_addresses.empty();

    pending_images.push_back(&image);
    pending_specs.push_back(std::move(bin_spec));
  }

  DynamicLoader::LocateBinaries(&process, pending_specs);

  for (auto [image, bin_spec] :
       llvm::zip_equal(pending_images, pending_specs)) {
    ModuleSP module_sp;
    if (llvm::Expected<ModuleSP> loaded =
            DynamicLoader::LoadBinaryInTarget(&process, bin_spec)) {
      module_sp = *loaded;
    } else if (bin_spec.force_symbol_search) {
      *process.GetTarget().GetDebugger().GetAsyncErrorStream()
          << llvm::toString(loaded.takeError()) << "\n";
    } else {
      // A corefile image that isn't on this machine is routine, and has
      // already been logged.
      llvm::consumeError(loaded.takeError());
    }

    if (!module_sp)
      continue;

    added_modules.Append(module_sp, false /* notify */);

    // We have a list of segment load address
    if (image->segment_load_addresses.size() > 0) {
      if (log) {
        std::string uuidstr = image->uuid.GetAsString();
        log->Printf("ObjectFileMachO::LoadCoreFileImages adding binary '%s' "
                    "UUID %s with section load addresses",
                    module_sp->GetFileSpec().GetPath().c_str(),
                    uuidstr.c_str());
      }
      ObjectFile *objfile = module_sp->GetObjectFile();
      SectionList *sectlist = objfile ? objfile->GetSectionList() : nullptr;
      for (auto name_vmaddr_tuple : image->segment_load_addresses) {
        if (sectlist) {
          SectionSP sect_sp =
              sectlist->FindSectionByName(std::get<0>(name_vmaddr_tuple));
          if (sect_sp) {
            process.GetTarget().SetSectionLoadAddress(
                sect_sp, std::get<1>(name_vmaddr_tuple));
          }
        }
      }
    } else {
      if (log) {
        std::string uuidstr = image->uuid.GetAsString();
        log->Printf("ObjectFileMachO::LoadCoreFileImages adding binary '%s' "
                    "UUID %s with %s 0x%" PRIx64,
                    module_sp->GetFileSpec().GetPath().c_str(), uuidstr.c_str(),
                    bin_spec.value_is_offset ? "slide" : "load address",
                    bin_spec.value);
      }
      bool changed;
      module_sp->SetLoadAddress(process.GetTarget(), bin_spec.value,
                                bin_spec.value_is_offset, changed);
    }
  }

  if (added_modules.GetSize() > 0) {
    process.GetTarget().ModulesDidLoad(added_modules);
    process.Flush();
    return true;
  }
  // Return true if the only binary we found was the platform binary,
  // and it was loaded outside the scope of this method.
  if (found_platform_binary)
    return true;

  // No binaries.
  return false;
}
