//===-- ObjectFileELF.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 "ObjectFileELF.h"

#include <algorithm>
#include <cassert>
#include <optional>
#include <unordered_map>

#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/FileSystem.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MipsABIFlags.h"
#include "llvm/Support/RISCVAttributes.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/SubtargetFeature.h"

#define CASE_AND_STREAM(s, def, width)                                         \
  case def:                                                                    \
    s->Printf("%-*s", width, #def);                                            \
    break;

using namespace lldb;
using namespace lldb_private;
using namespace elf;
using namespace llvm::ELF;

LLDB_PLUGIN_DEFINE(ObjectFileELF)

// ELF note owner definitions
static const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
static const char *const LLDB_NT_OWNER_GNU = "GNU";
static const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
static const char *const LLDB_NT_OWNER_NETBSDCORE = "NetBSD-CORE";
static const char *const LLDB_NT_OWNER_OPENBSD = "OpenBSD";
static const char *const LLDB_NT_OWNER_ANDROID = "Android";
static const char *const LLDB_NT_OWNER_CORE = "CORE";
static const char *const LLDB_NT_OWNER_LINUX = "LINUX";

// ELF note type definitions
static const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
static const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4;

static const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
static const elf_word LLDB_NT_GNU_ABI_SIZE = 16;

static const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;

static const elf_word LLDB_NT_NETBSD_IDENT_TAG = 1;
static const elf_word LLDB_NT_NETBSD_IDENT_DESCSZ = 4;
static const elf_word LLDB_NT_NETBSD_IDENT_NAMESZ = 7;
static const elf_word LLDB_NT_NETBSD_PROCINFO = 1;

// GNU ABI note OS constants
static const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
static const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
static const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;

namespace {

//===----------------------------------------------------------------------===//
/// \class ELFRelocation
/// Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
class ELFRelocation {
public:
  /// Constructs an ELFRelocation entry with a personality as given by @p
  /// type.
  ///
  /// \param type Either DT_REL or DT_RELA.  Any other value is invalid.
  ELFRelocation(unsigned type);

  ~ELFRelocation();

  bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);

  static unsigned RelocType32(const ELFRelocation &rel);

  static unsigned RelocType64(const ELFRelocation &rel);

  static unsigned RelocSymbol32(const ELFRelocation &rel);

  static unsigned RelocSymbol64(const ELFRelocation &rel);

  static elf_addr RelocOffset32(const ELFRelocation &rel);

  static elf_addr RelocOffset64(const ELFRelocation &rel);

  static elf_sxword RelocAddend32(const ELFRelocation &rel);

  static elf_sxword RelocAddend64(const ELFRelocation &rel);

  bool IsRela() { return (llvm::isa<ELFRela *>(reloc)); }

private:
  typedef llvm::PointerUnion<ELFRel *, ELFRela *> RelocUnion;

  RelocUnion reloc;
};

lldb::SectionSP MergeSections(lldb::SectionSP lhs, lldb::SectionSP rhs) {
  assert(lhs && rhs);

  lldb::ModuleSP lhs_module_parent = lhs->GetModule();
  lldb::ModuleSP rhs_module_parent = rhs->GetModule();
  assert(lhs_module_parent && rhs_module_parent);

  // Do a sanity check, these should be the same.
  if (lhs->GetFileAddress() != rhs->GetFileAddress())
    lhs_module_parent->ReportWarning(
        "mismatch addresses for section {0} when "
        "merging with {1}, expected: {2:x}, "
        "actual: {3:x}",
        lhs->GetTypeAsCString(), rhs_module_parent->GetFileSpec().GetPath(),
        lhs->GetFileAddress(), rhs->GetFileAddress());

  // We want to take the greater of two sections. If LHS and RHS are both
  // SHT_NOBITS, we should default to LHS. If RHS has a bigger section,
  // indicating it has data that wasn't stripped, we should take that instead.
  return rhs->GetFileSize() > lhs->GetFileSize() ? rhs : lhs;
}
} // end anonymous namespace

ELFRelocation::ELFRelocation(unsigned type) {
  if (type == DT_REL || type == SHT_REL)
    reloc = new ELFRel();
  else if (type == DT_RELA || type == SHT_RELA)
    reloc = new ELFRela();
  else {
    assert(false && "unexpected relocation type");
    reloc = static_cast<ELFRel *>(nullptr);
  }
}

ELFRelocation::~ELFRelocation() {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(reloc))
    delete elfrel;
  else
    delete llvm::cast<ELFRela *>(reloc);
}

bool ELFRelocation::Parse(const lldb_private::DataExtractor &data,
                          lldb::offset_t *offset) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(reloc))
    return elfrel->Parse(data, offset);
  else
    return llvm::cast<ELFRela *>(reloc)->Parse(data, offset);
}

unsigned ELFRelocation::RelocType32(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return ELFRel::RelocType32(*elfrel);
  else
    return ELFRela::RelocType32(*llvm::cast<ELFRela *>(rel.reloc));
}

unsigned ELFRelocation::RelocType64(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return ELFRel::RelocType64(*elfrel);
  else
    return ELFRela::RelocType64(*llvm::cast<ELFRela *>(rel.reloc));
}

unsigned ELFRelocation::RelocSymbol32(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return ELFRel::RelocSymbol32(*elfrel);
  else
    return ELFRela::RelocSymbol32(*llvm::cast<ELFRela *>(rel.reloc));
}

unsigned ELFRelocation::RelocSymbol64(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return ELFRel::RelocSymbol64(*elfrel);
  else
    return ELFRela::RelocSymbol64(*llvm::cast<ELFRela *>(rel.reloc));
}

elf_addr ELFRelocation::RelocOffset32(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return elfrel->r_offset;
  else
    return llvm::cast<ELFRela *>(rel.reloc)->r_offset;
}

elf_addr ELFRelocation::RelocOffset64(const ELFRelocation &rel) {
  if (auto *elfrel = llvm::dyn_cast<ELFRel *>(rel.reloc))
    return elfrel->r_offset;
  else
    return llvm::cast<ELFRela *>(rel.reloc)->r_offset;
}

elf_sxword ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
  if (llvm::isa<ELFRel *>(rel.reloc))
    return 0;
  else
    return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
}

elf_sxword  ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
  if (llvm::isa<ELFRel *>(rel.reloc))
    return 0;
  else
    return llvm::cast<ELFRela *>(rel.reloc)->r_addend;
}

static user_id_t SegmentID(size_t PHdrIndex) {
  return ~user_id_t(PHdrIndex);
}

bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
  // Read all fields.
  if (data.GetU32(offset, &n_namesz, 3) == nullptr)
    return false;

  // The name field is required to be null-terminated, and n_namesz includes the
  // terminating nul in observed implementations (contrary to the ELF-64 spec).
  // A special case is needed for cores generated by some older Linux versions,
  // which write a note named "CORE" without a null terminator and n_namesz = 4.
  if (n_namesz == 4) {
    char buf[4];
    if (data.ExtractBytes(*offset, 4, data.GetByteOrder(), buf) != 4)
      return false;
    if (strncmp(buf, "CORE", 4) == 0) {
      n_name = "CORE";
      *offset += 4;
      return true;
    }
  }

  const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4));
  if (cstr == nullptr) {
    Log *log = GetLog(LLDBLog::Symbols);
    LLDB_LOGF(log, "Failed to parse note name lacking null terminator");

    return false;
  }
  n_name = cstr;
  return true;
}

static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
  const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH;
  uint32_t endian = header.e_ident[EI_DATA];
  uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
  uint32_t fileclass = header.e_ident[EI_CLASS];

  // If there aren't any elf flags available (e.g core elf file) then return
  // default
  // 32 or 64 bit arch (without any architecture revision) based on object file's class.
  if (header.e_type == ET_CORE) {
    switch (fileclass) {
    case llvm::ELF::ELFCLASS32:
      return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el
                                     : ArchSpec::eMIPSSubType_mips32;
    case llvm::ELF::ELFCLASS64:
      return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el
                                     : ArchSpec::eMIPSSubType_mips64;
    default:
      return arch_variant;
    }
  }

  switch (mips_arch) {
  case llvm::ELF::EF_MIPS_ARCH_1:
  case llvm::ELF::EF_MIPS_ARCH_2:
  case llvm::ELF::EF_MIPS_ARCH_32:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el
                                   : ArchSpec::eMIPSSubType_mips32;
  case llvm::ELF::EF_MIPS_ARCH_32R2:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el
                                   : ArchSpec::eMIPSSubType_mips32r2;
  case llvm::ELF::EF_MIPS_ARCH_32R6:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el
                                   : ArchSpec::eMIPSSubType_mips32r6;
  case llvm::ELF::EF_MIPS_ARCH_3:
  case llvm::ELF::EF_MIPS_ARCH_4:
  case llvm::ELF::EF_MIPS_ARCH_5:
  case llvm::ELF::EF_MIPS_ARCH_64:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el
                                   : ArchSpec::eMIPSSubType_mips64;
  case llvm::ELF::EF_MIPS_ARCH_64R2:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r2el
                                   : ArchSpec::eMIPSSubType_mips64r2;
  case llvm::ELF::EF_MIPS_ARCH_64R6:
    return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r6el
                                   : ArchSpec::eMIPSSubType_mips64r6;
  default:
    break;
  }

  return arch_variant;
}

static uint32_t riscvVariantFromElfFlags(const elf::ELFHeader &header) {
  uint32_t fileclass = header.e_ident[EI_CLASS];
  switch (fileclass) {
  case llvm::ELF::ELFCLASS32:
    return ArchSpec::eRISCVSubType_riscv32;
  case llvm::ELF::ELFCLASS64:
    return ArchSpec::eRISCVSubType_riscv64;
  default:
    return ArchSpec::eRISCVSubType_unknown;
  }
}

static uint32_t ppc64VariantFromElfFlags(const elf::ELFHeader &header) {
  uint32_t endian = header.e_ident[EI_DATA];
  if (endian == ELFDATA2LSB)
    return ArchSpec::eCore_ppc64le_generic;
  else
    return ArchSpec::eCore_ppc64_generic;
}

static uint32_t loongarchVariantFromElfFlags(const elf::ELFHeader &header) {
  uint32_t fileclass = header.e_ident[EI_CLASS];
  switch (fileclass) {
  case llvm::ELF::ELFCLASS32:
    return ArchSpec::eLoongArchSubType_loongarch32;
  case llvm::ELF::ELFCLASS64:
    return ArchSpec::eLoongArchSubType_loongarch64;
  default:
    return ArchSpec::eLoongArchSubType_unknown;
  }
}

static uint32_t AMDGPUVariantFromElfFlags(const elf::ELFHeader &header) {
  // Only HSA objects encode the exact GPU model, as an EF_AMDGPU_MACH value.
  if (header.e_ident[EI_OSABI] == ELFOSABI_AMDGPU_HSA) {
    switch (header.e_ident[EI_ABIVERSION]) {
    // HSA V2 does not encode a CPU model.
    case ELFABIVERSION_AMDGPU_HSA_V2:
      break;

    case ELFABIVERSION_AMDGPU_HSA_V3:
    case ELFABIVERSION_AMDGPU_HSA_V4:
    case ELFABIVERSION_AMDGPU_HSA_V5:
    case ELFABIVERSION_AMDGPU_HSA_V6:
      // The CPU model is the EF_AMDGPU_MACH value in the bottom byte of
      // e_flags.
      return header.e_flags & EF_AMDGPU_MACH;
    }
  }
  return LLDB_INVALID_CPUTYPE;
}

static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) {
  if (header.e_machine == llvm::ELF::EM_MIPS)
    return mipsVariantFromElfFlags(header);
  else if (header.e_machine == llvm::ELF::EM_PPC64)
    return ppc64VariantFromElfFlags(header);
  else if (header.e_machine == llvm::ELF::EM_RISCV)
    return riscvVariantFromElfFlags(header);
  else if (header.e_machine == llvm::ELF::EM_LOONGARCH)
    return loongarchVariantFromElfFlags(header);
  else if (header.e_machine == llvm::ELF::EM_AMDGPU)
    return AMDGPUVariantFromElfFlags(header);

  return LLDB_INVALID_CPUTYPE;
}

char ObjectFileELF::ID;

// Arbitrary constant used as UUID prefix for core files.
const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C);

// Static methods.
void ObjectFileELF::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                CreateMemoryInstance, GetModuleSpecifications);
}

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

ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
                                          DataExtractorSP extractor_sp,
                                          lldb::offset_t data_offset,
                                          const lldb_private::FileSpec *file,
                                          lldb::offset_t file_offset,
                                          lldb::offset_t length) {
  bool mapped_writable = false;
  if (!extractor_sp || !extractor_sp->HasData()) {
    DataBufferSP buffer_sp = MapFileDataWritable(*file, length, file_offset);
    if (!buffer_sp)
      return nullptr;
    extractor_sp = std::make_shared<DataExtractor>(buffer_sp);
    data_offset = 0;
    mapped_writable = true;
  }

  assert(extractor_sp && extractor_sp->HasData());

  DataBufferSP data_sp = extractor_sp->GetSharedDataBuffer();

  if (data_sp->GetByteSize() <= (llvm::ELF::EI_NIDENT + data_offset))
    return nullptr;

  const uint8_t *magic = data_sp->GetBytes() + data_offset;
  if (!ELFHeader::MagicBytesMatch(magic))
    return nullptr;

  // Update the data to contain the entire file if it doesn't already
  if (data_sp->GetByteSize() < length) {
    data_sp = MapFileDataWritable(*file, length, file_offset);
    if (!data_sp)
      return nullptr;
    data_offset = 0;
    mapped_writable = true;
    magic = data_sp->GetBytes();
    extractor_sp->SetData(data_sp);
  }

  // If we didn't map the data as writable take ownership of the buffer.
  if (!mapped_writable) {
    data_sp = std::make_shared<DataBufferHeap>(data_sp->GetBytes(),
                                               data_sp->GetByteSize());
    data_offset = 0;
    magic = data_sp->GetBytes();
    extractor_sp->SetData(data_sp);
  }

  unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
  if (address_size == 4 || address_size == 8) {
    extractor_sp->SetAddressByteSize(address_size);
    std::unique_ptr<ObjectFileELF> objfile_up(new ObjectFileELF(
        module_sp, extractor_sp, data_offset, file, file_offset, length));
    ArchSpec spec = objfile_up->GetArchitecture();
    if (spec && objfile_up->SetModulesArchitecture(spec))
      return objfile_up.release();
  }

  return nullptr;
}

ObjectFile *ObjectFileELF::CreateMemoryInstance(
    const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
    const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
  if (!data_sp || data_sp->GetByteSize() < (llvm::ELF::EI_NIDENT))
    return nullptr;
  const uint8_t *magic = data_sp->GetBytes();
  if (!ELFHeader::MagicBytesMatch(magic))
    return nullptr;
  // Read the ELF header first so we can figure out how many bytes we need
  // to read to get as least the ELF header + program headers.
  DataExtractor data;
  data.SetData(data_sp);
  elf::ELFHeader hdr;
  lldb::offset_t offset = 0;
  if (!hdr.Parse(data, &offset))
    return nullptr;

  // Make sure the address size is set correctly in the ELF header.
  if (!hdr.Is32Bit() && !hdr.Is64Bit())
    return nullptr;
  // Figure out where the program headers end and read enough bytes to get the
  // program headers in their entirety.
  lldb::offset_t end_phdrs = hdr.e_phoff + (hdr.e_phentsize * hdr.e_phnum);
  if (end_phdrs > data_sp->GetByteSize())
    data_sp = ReadMemory(process_sp, header_addr, end_phdrs);

  std::unique_ptr<ObjectFileELF> objfile_up(
      new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
  ArchSpec spec = objfile_up->GetArchitecture();
  if (spec && objfile_up->SetModulesArchitecture(spec))
    return objfile_up.release();

  return nullptr;
}

bool ObjectFileELF::MagicBytesMatch(DataBufferSP data_sp,
                                    lldb::addr_t data_offset,
                                    lldb::addr_t data_length) {
  if (data_sp &&
      data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset)) {
    const uint8_t *magic = data_sp->GetBytes() + data_offset;
    return ELFHeader::MagicBytesMatch(magic);
  }
  return false;
}

static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) {
  return llvm::crc32(init,
                     llvm::ArrayRef(data.GetDataStart(), data.GetByteSize()));
}

uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
    const ProgramHeaderColl &program_headers, DataExtractor &object_data) {

  uint32_t core_notes_crc = 0;

  for (const ELFProgramHeader &H : program_headers) {
    if (H.p_type == llvm::ELF::PT_NOTE) {
      const elf_off ph_offset = H.p_offset;
      const size_t ph_size = H.p_filesz;

      DataExtractor segment_data;
      if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
        // The ELF program header contained incorrect data, probably corefile
        // is incomplete or corrupted.
        break;
      }

      core_notes_crc = calc_crc32(core_notes_crc, segment_data);
    }
  }

  return core_notes_crc;
}

static const char *OSABIAsCString(unsigned char osabi_byte) {
#define _MAKE_OSABI_CASE(x)                                                    \
  case x:                                                                      \
    return #x
  switch (osabi_byte) {
    _MAKE_OSABI_CASE(ELFOSABI_NONE);
    _MAKE_OSABI_CASE(ELFOSABI_HPUX);
    _MAKE_OSABI_CASE(ELFOSABI_NETBSD);
    _MAKE_OSABI_CASE(ELFOSABI_GNU);
    _MAKE_OSABI_CASE(ELFOSABI_HURD);
    _MAKE_OSABI_CASE(ELFOSABI_SOLARIS);
    _MAKE_OSABI_CASE(ELFOSABI_AIX);
    _MAKE_OSABI_CASE(ELFOSABI_IRIX);
    _MAKE_OSABI_CASE(ELFOSABI_FREEBSD);
    _MAKE_OSABI_CASE(ELFOSABI_TRU64);
    _MAKE_OSABI_CASE(ELFOSABI_MODESTO);
    _MAKE_OSABI_CASE(ELFOSABI_OPENBSD);
    _MAKE_OSABI_CASE(ELFOSABI_OPENVMS);
    _MAKE_OSABI_CASE(ELFOSABI_NSK);
    _MAKE_OSABI_CASE(ELFOSABI_AROS);
    _MAKE_OSABI_CASE(ELFOSABI_FENIXOS);
    _MAKE_OSABI_CASE(ELFOSABI_C6000_ELFABI);
    _MAKE_OSABI_CASE(ELFOSABI_C6000_LINUX);
    _MAKE_OSABI_CASE(ELFOSABI_ARM);
    _MAKE_OSABI_CASE(ELFOSABI_STANDALONE);
  default:
    return "<unknown-osabi>";
  }
#undef _MAKE_OSABI_CASE
}

//
// WARNING : This function is being deprecated
// It's functionality has moved to ArchSpec::SetArchitecture This function is
// only being kept to validate the move.
//
// TODO : Remove this function
static bool GetOsFromOSABI(unsigned char osabi_byte,
                           llvm::Triple::OSType &ostype) {
  switch (osabi_byte) {
  case ELFOSABI_AIX:
    ostype = llvm::Triple::OSType::AIX;
    break;
  case ELFOSABI_FREEBSD:
    ostype = llvm::Triple::OSType::FreeBSD;
    break;
  case ELFOSABI_GNU:
    ostype = llvm::Triple::OSType::Linux;
    break;
  case ELFOSABI_NETBSD:
    ostype = llvm::Triple::OSType::NetBSD;
    break;
  case ELFOSABI_OPENBSD:
    ostype = llvm::Triple::OSType::OpenBSD;
    break;
  case ELFOSABI_SOLARIS:
    ostype = llvm::Triple::OSType::Solaris;
    break;
  case ELFOSABI_AMDGPU_HSA:
    ostype = llvm::Triple::OSType::AMDHSA;
    break;
  default:
    ostype = llvm::Triple::OSType::UnknownOS;
  }
  return ostype != llvm::Triple::OSType::UnknownOS;
}

ModuleSpecList ObjectFileELF::GetModuleSpecifications(
    const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp,
    lldb::offset_t file_offset, lldb::offset_t length) {
  Log *log = GetLog(LLDBLog::Modules);

  if (!extractor_sp || !extractor_sp->HasData())
    return {};
  if (ObjectFileELF::MagicBytesMatch(extractor_sp->GetSharedDataBuffer(), 0,
                                     extractor_sp->GetByteSize())) {
    elf::ELFHeader header;
    lldb::offset_t header_offset = 0;
    if (header.Parse(*extractor_sp, &header_offset)) {
      ModuleSpec spec(file);
      // In Android API level 23 and above, bionic dynamic linker is able to
      // load .so file directly from zip file. In that case, .so file is
      // page aligned and uncompressed, and this module spec should retain the
      // .so file offset and file size to pass through the information from
      // lldb-server to LLDB. For normal file, file_offset should be 0,
      // length should be the size of the file.
      spec.SetObjectOffset(file_offset);
      spec.SetObjectSize(length);

      const uint32_t sub_type = subTypeFromElfHeader(header);
      spec.GetArchitecture().SetArchitecture(
          eArchTypeELF, header.e_machine, sub_type, header.e_ident[EI_OSABI]);

      if (spec.GetArchitecture().IsValid()) {
        llvm::Triple::OSType ostype;
        llvm::Triple::OSType spec_ostype =
            spec.GetArchitecture().GetTriple().getOS();

        LLDB_LOGF(log, "ObjectFileELF::%s file '%s' module OSABI: %s",
                  __FUNCTION__, file.GetPath().c_str(),
                  OSABIAsCString(header.e_ident[EI_OSABI]));

        // Validate it is ok to remove GetOsFromOSABI
        GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
        assert(spec_ostype == ostype);
        if (spec_ostype != llvm::Triple::OSType::UnknownOS) {
          LLDB_LOGF(log,
                    "ObjectFileELF::%s file '%s' set ELF module OS type "
                    "from ELF header OSABI.",
                    __FUNCTION__, file.GetPath().c_str());
        }

        // When ELF file does not contain GNU build ID, the later code will
        // calculate CRC32 with this data file_offset and
        // length. It is important for Android zip .so file, which is a slice
        // of a file, to not access the outside of the file slice range.
        if (extractor_sp->GetByteSize() < length)
          if (DataBufferSP data_sp = MapFileData(file, length, file_offset)) {
            extractor_sp->SetData(data_sp);
          }
        // In case there is header extension in the section #0, the header we
        // parsed above could have sentinel values for e_phnum, e_shnum, and
        // e_shstrndx.  In this case we need to reparse the header with a
        // bigger data source to get the actual values.
        if (header.HasHeaderExtension()) {
          lldb::offset_t header_offset = 0;
          header.Parse(*extractor_sp, &header_offset);
        }

        uint32_t gnu_debuglink_crc = 0;
        std::string gnu_debuglink_file;
        SectionHeaderColl section_headers;
        lldb_private::UUID &uuid = spec.GetUUID();

        GetSectionHeaderInfo(section_headers, *extractor_sp, header, uuid,
                             gnu_debuglink_file, gnu_debuglink_crc,
                             spec.GetArchitecture());

        llvm::Triple &spec_triple = spec.GetArchitecture().GetTriple();

        LLDB_LOGF(log,
                  "ObjectFileELF::%s file '%s' module set to triple: %s "
                  "(architecture %s)",
                  __FUNCTION__, file.GetPath().c_str(),
                  spec_triple.getTriple().c_str(),
                  spec.GetArchitecture().GetArchitectureName());

        if (!uuid.IsValid()) {
          uint32_t core_notes_crc = 0;

          if (!gnu_debuglink_crc) {
            LLDB_SCOPED_TIMERF("Calculating module crc32 %s with size %" PRIu64
                               " KiB",
                               file.GetFilename().str().c_str(),
                               (length - file_offset) / 1024);

            // For core files - which usually don't happen to have a
            // gnu_debuglink, and are pretty bulky - calculating whole
            // contents crc32 would be too much of luxury.  Thus we will need
            // to fallback to something simpler.
            if (header.e_type == llvm::ELF::ET_CORE) {
              ProgramHeaderColl program_headers;
              GetProgramHeaderInfo(program_headers, *extractor_sp, header);

              core_notes_crc = CalculateELFNotesSegmentsCRC32(program_headers,
                                                              *extractor_sp);
            } else {
              gnu_debuglink_crc = calc_crc32(0, *extractor_sp);
            }
          }
          using u32le = llvm::support::ulittle32_t;
          if (gnu_debuglink_crc) {
            // Use 4 bytes of crc from the .gnu_debuglink section.
            u32le data(gnu_debuglink_crc);
            uuid = UUID(&data, sizeof(data));
          } else if (core_notes_crc) {
            // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make
            // it look different form .gnu_debuglink crc followed by 4 bytes
            // of note segments crc.
            u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
            uuid = UUID(data, sizeof(data));
          }
        }

        ModuleSpecList specs;
        specs.Append(spec);
        return specs;
      }
    }
  }

  return {};
}

// ObjectFile protocol

ObjectFileELF::ObjectFileELF(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) {
  if (file)
    m_file = *file;
}

ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
                             DataBufferSP header_data_sp,
                             const lldb::ProcessSP &process_sp,
                             addr_t header_addr)
    : ObjectFile(module_sp, process_sp, header_addr,
                 std::make_shared<DataExtractor>(header_data_sp)) {}

bool ObjectFileELF::IsExecutable() const {
  return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0);
}

bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
                                   bool value_is_offset) {
  ModuleSP module_sp = GetModule();
  if (module_sp) {
    size_t num_loaded_sections = 0;
    SectionList *section_list = GetSectionList();
    if (section_list) {
      if (!value_is_offset) {
        addr_t base = GetBaseAddress().GetFileAddress();
        if (base == LLDB_INVALID_ADDRESS)
          return false;
        value -= base;
      }

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

      for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
        // Iterate through the object file sections to find all of the sections
        // that have SHF_ALLOC in their flag bits.
        SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));

        // PT_TLS segments can have the same p_vaddr and p_paddr as other
        // PT_LOAD segments so we shouldn't load them. If we do load them, then
        // the SectionLoadList will incorrectly fill in the instance variable
        // SectionLoadList::m_addr_to_sect with the same address as a PT_LOAD
        // segment and we won't be able to resolve addresses in the PT_LOAD
        // segment whose p_vaddr entry matches that of the PT_TLS. Any variables
        // that appear in the PT_TLS segments get resolved by the DWARF
        // expressions. If this ever changes we will need to fix all object
        // file plug-ins, but until then, we don't want PT_TLS segments to
        // remove the entry from SectionLoadList::m_addr_to_sect when we call
        // SetSectionLoadAddress() below.
        if (section_sp->IsThreadSpecific())
          continue;
        if (section_sp->Test(SHF_ALLOC) ||
            section_sp->GetType() == eSectionTypeContainer) {
          lldb::addr_t load_addr = section_sp->GetFileAddress();
          // We don't want to update the load address of a section with type
          // eSectionTypeAbsoluteAddress as they already have the absolute load
          // address already specified
          if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
            load_addr += value;

          // On 32-bit systems the load address have to fit into 4 bytes. The
          // rest of the bytes are the overflow from the addition.
          if (GetAddressByteSize() == 4)
            load_addr &= 0xFFFFFFFF;

          if (target.SetSectionLoadAddress(section_sp, load_addr))
            ++num_loaded_sections;
        }
      }
      return num_loaded_sections > 0;
    }
  }
  return false;
}

ByteOrder ObjectFileELF::GetByteOrder() const {
  if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
    return eByteOrderBig;
  if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
    return eByteOrderLittle;
  return eByteOrderInvalid;
}

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

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

  // The address class is determined based on the symtab. Ask it from the
  // object file what contains the symtab information.
  ObjectFile *symtab_objfile = symtab->GetObjectFile();
  if (symtab_objfile != nullptr && symtab_objfile != this)
    return symtab_objfile->GetAddressClass(file_addr);

  auto res = ObjectFile::GetAddressClass(file_addr);
  if (res != AddressClass::eCode)
    return res;

  auto ub = m_address_class_map.upper_bound(file_addr);
  if (ub == m_address_class_map.begin()) {
    // No entry in the address class map before the address. Return default
    // address class for an address in a code section.
    return AddressClass::eCode;
  }

  // Move iterator to the address class entry preceding address
  --ub;

  return ub->second;
}

size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) {
  return std::distance(m_section_headers.begin(), I);
}

size_t ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const {
  return std::distance(m_section_headers.begin(), I);
}

bool ObjectFileELF::ParseHeader() {
  lldb::offset_t offset = 0;
  return m_header.Parse(*m_data_nsp, &offset);
}

UUID ObjectFileELF::GetUUID() {
  if (m_uuid)
    return m_uuid;

  // Try loading note info from any PT_NOTE program headers. This is more
  // friendly to ELF files that have no section headers, like ELF files that
  // are loaded from memory.
  for (const ELFProgramHeader &H : ProgramHeaders()) {
    if (H.p_type == llvm::ELF::PT_NOTE) {
      DataExtractor note_data = GetSegmentData(H);
      if (note_data.GetByteSize()) {
        lldb_private::ArchSpec arch_spec;
        RefineModuleDetailsFromNote(note_data, arch_spec, m_uuid);
        if (m_uuid)
          return m_uuid;
      }
    }
  }

  // Need to parse the section list to get the UUIDs, so make sure that's been
  // done.
  if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
    return UUID();

  if (!m_uuid) {
    using u32le = llvm::support::ulittle32_t;
    if (GetType() == ObjectFile::eTypeCoreFile) {
      uint32_t core_notes_crc = 0;

      if (!ParseProgramHeaders())
        return UUID();

      core_notes_crc =
          CalculateELFNotesSegmentsCRC32(m_program_headers, *m_data_nsp);

      if (core_notes_crc) {
        // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
        // look different form .gnu_debuglink crc - followed by 4 bytes of note
        // segments crc.
        u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
        m_uuid = UUID(data, sizeof(data));
      }
    } else {
      if (!m_gnu_debuglink_crc)
        m_gnu_debuglink_crc = calc_crc32(0, *m_data_nsp);
      if (m_gnu_debuglink_crc) {
        // Use 4 bytes of crc from the .gnu_debuglink section.
        u32le data(m_gnu_debuglink_crc);
        m_uuid = UUID(&data, sizeof(data));
      }
    }
  }

  return m_uuid;
}

std::optional<FileSpec> ObjectFileELF::GetDebugLink() {
  if (m_gnu_debuglink_file.empty())
    return std::nullopt;
  return FileSpec(m_gnu_debuglink_file);
}

uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) {
  size_t num_modules = ParseDependentModules();
  uint32_t num_specs = 0;

  for (unsigned i = 0; i < num_modules; ++i) {
    if (files.AppendIfUnique(m_filespec_up->GetFileSpecAtIndex(i)))
      num_specs++;
  }

  return num_specs;
}

Address ObjectFileELF::GetImageInfoAddress(Target *target) {
  if (!ParseDynamicSymbols())
    return Address();

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

  for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) {
    const ELFDynamic &symbol = m_dynamic_symbols[i].symbol;

    if (symbol.d_tag != DT_DEBUG && symbol.d_tag != DT_MIPS_RLD_MAP &&
        symbol.d_tag != DT_MIPS_RLD_MAP_REL)
      continue;

    // Compute the offset as the number of previous entries plus the size of
    // d_tag.
    const addr_t offset = (i * 2 + 1) * GetAddressByteSize();
    const addr_t d_file_addr = m_dynamic_base_addr + offset;
    Address d_addr;
    if (!d_addr.ResolveAddressUsingFileSections(d_file_addr, GetSectionList()))
      return Address();
    if (symbol.d_tag == DT_DEBUG)
      return d_addr;

    // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP
    // exists in non-PIE.
    if ((symbol.d_tag == DT_MIPS_RLD_MAP ||
         symbol.d_tag == DT_MIPS_RLD_MAP_REL) &&
        target) {
      const addr_t d_load_addr = d_addr.GetLoadAddress(target);
      if (d_load_addr == LLDB_INVALID_ADDRESS)
        return Address();

      Status error;
      if (symbol.d_tag == DT_MIPS_RLD_MAP) {
        // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
        Address addr;
        if (target->ReadPointerFromMemory(Address(d_load_addr), error, addr,
                                          true))
          return addr;
      }
      if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) {
        // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer,
        // relative to the address of the tag.
        uint64_t rel_offset;
        rel_offset = target->ReadUnsignedIntegerFromMemory(
            Address(d_load_addr), GetAddressByteSize(), UINT64_MAX, error,
            true);
        if (error.Success() && rel_offset != UINT64_MAX) {
          Address addr;
          addr_t debug_ptr_address =
              d_load_addr - GetAddressByteSize() + rel_offset;
          addr.SetOffset(debug_ptr_address);
          return addr;
        }
      }
    }
  }
  return Address();
}

lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
  if (m_entry_point_address.IsValid())
    return m_entry_point_address;

  if (!ParseHeader() || !IsExecutable())
    return m_entry_point_address;

  SectionList *section_list = GetSectionList();
  addr_t offset = m_header.e_entry;

  if (!section_list)
    m_entry_point_address.SetOffset(offset);
  else
    m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
  return m_entry_point_address;
}

Address ObjectFileELF::GetBaseAddress() {
  if (GetType() == ObjectFile::eTypeObjectFile) {
    for (SectionHeaderCollIter I = std::next(m_section_headers.begin());
         I != m_section_headers.end(); ++I) {
      const ELFSectionHeaderInfo &header = *I;
      if (header.sh_flags & SHF_ALLOC)
        return Address(GetSectionList()->FindSectionByID(SectionIndex(I)), 0);
    }
    return Address();
  }

  for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
    const ELFProgramHeader &H = EnumPHdr.value();
    if (H.p_type != PT_LOAD)
      continue;

    return Address(
        GetSectionList()->FindSectionByID(SegmentID(EnumPHdr.index())), 0);
  }
  return Address();
}

FileSpecList ObjectFileELF::GetReExportedLibraries() {
  FileSpecList filtees;
  if (!ParseDynamicSymbols())
    return filtees;
  // Multiple DT_FILTER / DT_AUXILIARY entries are permitted; the dynamic
  // linker searches the filtees in the order the entries appear in the
  // dynamic section, so preserve that order here.
  for (const auto &entry : m_dynamic_symbols) {
    if (entry.symbol.d_tag != DT_FILTER && entry.symbol.d_tag != DT_AUXILIARY)
      continue;
    if (!entry.name.empty())
      filtees.EmplaceBack(entry.name);
  }
  return filtees;
}

size_t ObjectFileELF::ParseDependentModules() {
  if (m_filespec_up)
    return m_filespec_up->GetSize();

  m_filespec_up = std::make_unique<FileSpecList>();

  if (ParseDynamicSymbols()) {
    for (const auto &entry : m_dynamic_symbols) {
      if (entry.symbol.d_tag != DT_NEEDED)
        continue;
      if (!entry.name.empty()) {
        FileSpec file_spec(entry.name);
        FileSystem::Instance().Resolve(file_spec);
        m_filespec_up->Append(file_spec);
      }
    }
  }
  return m_filespec_up->GetSize();
}

// GetProgramHeaderInfo
size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
                                           DataExtractor &object_data,
                                           const ELFHeader &header) {
  // We have already parsed the program headers
  if (!program_headers.empty())
    return program_headers.size();

  // If there are no program headers to read we are done.
  if (header.e_phnum == 0)
    return 0;

  program_headers.resize(header.e_phnum);
  if (program_headers.size() != header.e_phnum)
    return 0;

  const size_t ph_size = header.e_phnum * header.e_phentsize;
  const elf_off ph_offset = header.e_phoff;
  DataExtractor data;
  if (data.SetData(object_data, ph_offset, ph_size) != ph_size)
    return 0;

  uint32_t idx;
  lldb::offset_t offset;
  for (idx = 0, offset = 0; idx < header.e_phnum; ++idx) {
    if (!program_headers[idx].Parse(data, &offset))
      break;
  }

  if (idx < program_headers.size())
    program_headers.resize(idx);

  return program_headers.size();
}

// ParseProgramHeaders
bool ObjectFileELF::ParseProgramHeaders() {
  return GetProgramHeaderInfo(m_program_headers, *m_data_nsp, m_header) != 0;
}

lldb_private::Status
ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
                                           lldb_private::ArchSpec &arch_spec,
                                           lldb_private::UUID &uuid) {
  Log *log = GetLog(LLDBLog::Modules);
  Status error;

  lldb::offset_t offset = 0;

  while (true) {
    // Parse the note header.  If this fails, bail out.
    const lldb::offset_t note_offset = offset;
    ELFNote note = ELFNote();
    if (!note.Parse(data, &offset)) {
      // We're done.
      return error;
    }

    LLDB_LOGF(log, "ObjectFileELF::%s parsing note name='%s', type=%" PRIu32,
              __FUNCTION__, note.n_name.c_str(), note.n_type);

    // Process FreeBSD ELF notes.
    if ((note.n_name == LLDB_NT_OWNER_FREEBSD) &&
        (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
        (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE)) {
      // Pull out the min version info.
      uint32_t version_info;
      if (data.GetU32(&offset, &version_info, 1) == nullptr) {
        error =
            Status::FromErrorString("failed to read FreeBSD ABI note payload");
        return error;
      }

      // Convert the version info into a major/minor number.
      const uint32_t version_major = version_info / 100000;
      const uint32_t version_minor = (version_info / 1000) % 100;

      char os_name[32];
      snprintf(os_name, sizeof(os_name), "freebsd%" PRIu32 ".%" PRIu32,
               version_major, version_minor);

      // Set the elf OS version to FreeBSD.  Also clear the vendor.
      arch_spec.GetTriple().setOSName(os_name);
      arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);

      LLDB_LOGF(log,
                "ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32
                ".%" PRIu32,
                __FUNCTION__, version_major, version_minor,
                static_cast<uint32_t>(version_info % 1000));
    }
    // Process GNU ELF notes.
    else if (note.n_name == LLDB_NT_OWNER_GNU) {
      switch (note.n_type) {
      case LLDB_NT_GNU_ABI_TAG:
        if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE) {
          // Pull out the min OS version supporting the ABI.
          uint32_t version_info[4];
          if (data.GetU32(&offset, &version_info[0], note.n_descsz / 4) ==
              nullptr) {
            error =
                Status::FromErrorString("failed to read GNU ABI note payload");
            return error;
          }

          // Set the OS per the OS field.
          switch (version_info[0]) {
          case LLDB_NT_GNU_ABI_OS_LINUX:
            arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
            arch_spec.GetTriple().setVendor(
                llvm::Triple::VendorType::UnknownVendor);
            LLDB_LOGF(log,
                      "ObjectFileELF::%s detected Linux, min version %" PRIu32
                      ".%" PRIu32 ".%" PRIu32,
                      __FUNCTION__, version_info[1], version_info[2],
                      version_info[3]);
            // FIXME we have the minimal version number, we could be propagating
            // that.  version_info[1] = OS Major, version_info[2] = OS Minor,
            // version_info[3] = Revision.
            break;
          case LLDB_NT_GNU_ABI_OS_HURD:
            arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
            arch_spec.GetTriple().setVendor(
                llvm::Triple::VendorType::UnknownVendor);
            LLDB_LOGF(log,
                      "ObjectFileELF::%s detected Hurd (unsupported), min "
                      "version %" PRIu32 ".%" PRIu32 ".%" PRIu32,
                      __FUNCTION__, version_info[1], version_info[2],
                      version_info[3]);
            break;
          case LLDB_NT_GNU_ABI_OS_SOLARIS:
            arch_spec.GetTriple().setOS(llvm::Triple::OSType::Solaris);
            arch_spec.GetTriple().setVendor(
                llvm::Triple::VendorType::UnknownVendor);
            LLDB_LOGF(log,
                      "ObjectFileELF::%s detected Solaris, min version %" PRIu32
                      ".%" PRIu32 ".%" PRIu32,
                      __FUNCTION__, version_info[1], version_info[2],
                      version_info[3]);
            break;
          default:
            LLDB_LOGF(log,
                      "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32
                      ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32,
                      __FUNCTION__, version_info[0], version_info[1],
                      version_info[2], version_info[3]);
            break;
          }
        }
        break;

      case LLDB_NT_GNU_BUILD_ID_TAG:
        // Only bother processing this if we don't already have the uuid set.
        if (!uuid.IsValid()) {
          // 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a
          // build-id of a different length. Accept it as long as it's at least
          // 4 bytes as it will be better than our own crc32.
          if (note.n_descsz >= 4) {
            if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) {
              // Save the build id as the UUID for the module.
              uuid = UUID(buf, note.n_descsz);
            } else {
              error = Status::FromErrorString(
                  "failed to read GNU_BUILD_ID note payload");
              return error;
            }
          }
        }
        break;
      }
      if (arch_spec.IsMIPS() &&
          arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
        // The note.n_name == LLDB_NT_OWNER_GNU is valid for Linux platform
        arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
    }
    // Process NetBSD ELF executables and shared libraries
    else if ((note.n_name == LLDB_NT_OWNER_NETBSD) &&
             (note.n_type == LLDB_NT_NETBSD_IDENT_TAG) &&
             (note.n_descsz == LLDB_NT_NETBSD_IDENT_DESCSZ) &&
             (note.n_namesz == LLDB_NT_NETBSD_IDENT_NAMESZ)) {
      // Pull out the version info.
      uint32_t version_info;
      if (data.GetU32(&offset, &version_info, 1) == nullptr) {
        error =
            Status::FromErrorString("failed to read NetBSD ABI note payload");
        return error;
      }
      // Convert the version info into a major/minor/patch number.
      //     #define __NetBSD_Version__ MMmmrrpp00
      //
      //     M = major version
      //     m = minor version; a minor number of 99 indicates current.
      //     r = 0 (since NetBSD 3.0 not used)
      //     p = patchlevel
      const uint32_t version_major = version_info / 100000000;
      const uint32_t version_minor = (version_info % 100000000) / 1000000;
      const uint32_t version_patch = (version_info % 10000) / 100;
      // Set the elf OS version to NetBSD.  Also clear the vendor.
      arch_spec.GetTriple().setOSName(
          llvm::formatv("netbsd{0}.{1}.{2}", version_major, version_minor,
                        version_patch).str());
      arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
    }
    // Process NetBSD ELF core(5) notes
    else if ((note.n_name == LLDB_NT_OWNER_NETBSDCORE) &&
             (note.n_type == LLDB_NT_NETBSD_PROCINFO)) {
      // Set the elf OS version to NetBSD.  Also clear the vendor.
      arch_spec.GetTriple().setOS(llvm::Triple::OSType::NetBSD);
      arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
    }
    // Process OpenBSD ELF notes.
    else if (note.n_name == LLDB_NT_OWNER_OPENBSD) {
      // Set the elf OS version to OpenBSD.  Also clear the vendor.
      arch_spec.GetTriple().setOS(llvm::Triple::OSType::OpenBSD);
      arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
    } else if (note.n_name == LLDB_NT_OWNER_ANDROID) {
      arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
      arch_spec.GetTriple().setEnvironment(
          llvm::Triple::EnvironmentType::Android);
    } else if (note.n_name == LLDB_NT_OWNER_LINUX) {
      // This is sometimes found in core files and usually contains extended
      // register info
      arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
    } else if (note.n_name == LLDB_NT_OWNER_CORE) {
      // Parse the NT_FILE to look for stuff in paths to shared libraries
      // The contents look like this in a 64 bit ELF core file:
      //
      // count     = 0x000000000000000a (10)
      // page_size = 0x0000000000001000 (4096)
      // Index start              end                file_ofs           path
      // ===== ------------------ ------------------ ------------------ -------------------------------------
      // [  0] 0x0000000000401000 0x0000000000000000                    /tmp/a.out
      // [  1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
      // [  2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
      // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
      // [  4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
      // [  5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
      // [  6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
      // [  7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
      // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
      // [  9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
      //
      // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
      // uint32_t.
      //
      // For reference: see readelf source code (in binutils).
      if (note.n_type == NT_FILE) {
        uint64_t count = data.GetAddress(&offset);
        const char *cstr;
        data.GetAddress(&offset); // Skip page size
        offset += count * 3 *
                  data.GetAddressByteSize(); // Skip all start/end/file_ofs
        for (size_t i = 0; i < count; ++i) {
          cstr = data.GetCStr(&offset);
          if (cstr == nullptr) {
            error = Status::FromErrorStringWithFormat(
                "ObjectFileELF::%s trying to read "
                "at an offset after the end "
                "(GetCStr returned nullptr)",
                __FUNCTION__);
            return error;
          }
          llvm::StringRef path(cstr);
          if (path.contains("/lib/x86_64-linux-gnu") || path.contains("/lib/i386-linux-gnu")) {
            arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
            break;
          }
        }
        if (arch_spec.IsMIPS() &&
            arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
          // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing for some
          // cases (e.g. compile with -nostdlib) Hence set OS to Linux
          arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
      }
    }

    // Calculate the offset of the next note just in case "offset" has been
    // used to poke at the contents of the note data
    offset = note_offset + note.GetByteSize();
  }

  return error;
}

void ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length,
                                       ArchSpec &arch_spec) {
  lldb::offset_t Offset = 0;

  uint8_t FormatVersion = data.GetU8(&Offset);
  if (FormatVersion != llvm::ELFAttrs::Format_Version)
    return;

  Offset = Offset + sizeof(uint32_t); // Section Length
  llvm::StringRef VendorName = data.GetCStr(&Offset);

  if (VendorName != "aeabi")
    return;

  if (arch_spec.GetTriple().getEnvironment() ==
      llvm::Triple::UnknownEnvironment)
    arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);

  while (Offset < length) {
    uint8_t Tag = data.GetU8(&Offset);
    uint32_t Size = data.GetU32(&Offset);

    if (Tag != llvm::ARMBuildAttrs::File || Size == 0)
      continue;

    while (Offset < length) {
      uint64_t Tag = data.GetULEB128(&Offset);
      switch (Tag) {
      default:
        if (Tag < 32)
          data.GetULEB128(&Offset);
        else if (Tag % 2 == 0)
          data.GetULEB128(&Offset);
        else
          data.GetCStr(&Offset);

        break;

      case llvm::ARMBuildAttrs::CPU_raw_name:
      case llvm::ARMBuildAttrs::CPU_name:
        data.GetCStr(&Offset);

        break;

      case llvm::ARMBuildAttrs::ABI_VFP_args: {
        uint64_t VFPArgs = data.GetULEB128(&Offset);

        if (VFPArgs == llvm::ARMBuildAttrs::BaseAAPCS) {
          if (arch_spec.GetTriple().getEnvironment() ==
                  llvm::Triple::UnknownEnvironment ||
              arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABIHF)
            arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);

          arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
        } else if (VFPArgs == llvm::ARMBuildAttrs::HardFPAAPCS) {
          if (arch_spec.GetTriple().getEnvironment() ==
                  llvm::Triple::UnknownEnvironment ||
              arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABI)
            arch_spec.GetTriple().setEnvironment(llvm::Triple::EABIHF);

          arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
        }

        break;
      }
      }
    }
  }
}

static std::optional<lldb::offset_t>
FindSubSectionOffsetByName(const DataExtractor &data, lldb::offset_t offset,
                           uint32_t length, llvm::StringRef name) {
  uint32_t section_length = 0;
  llvm::StringRef section_name;
  do {
    offset += section_length;
    // Sub-section's size and name are included in the total sub-section length.
    // Don't shift the offset here, so it will point at the beginning of the
    // sub-section and could be used as a return value.
    auto tmp_offset = offset;
    section_length = data.GetU32(&tmp_offset);
    section_name = data.GetCStr(&tmp_offset);
  } while (section_name != name && offset + section_length < length);

  if (section_name == name)
    return offset;

  return std::nullopt;
}

static std::optional<lldb::offset_t>
FindSubSubSectionOffsetByTag(const DataExtractor &data, lldb::offset_t offset,
                             unsigned tag) {
  // Consume a sub-section size and name to shift the offset at the beginning of
  // the sub-sub-sections list.
  auto parent_section_length = data.GetU32(&offset);
  data.GetCStr(&offset);
  auto parent_section_end_offset = offset + parent_section_length;

  uint32_t section_length = 0;
  unsigned section_tag = 0;
  do {
    offset += section_length;
    // Similar to sub-section sub-sub-section's tag and size are included in the
    // total sub-sub-section length.
    auto tmp_offset = offset;
    section_tag = data.GetULEB128(&tmp_offset);
    section_length = data.GetU32(&tmp_offset);
  } while (section_tag != tag &&
           offset + section_length < parent_section_end_offset);

  if (section_tag == tag)
    return offset;

  return std::nullopt;
}

static std::optional<std::variant<uint64_t, llvm::StringRef>>
GetAttributeValueByTag(const DataExtractor &data, lldb::offset_t offset,
                       unsigned tag) {
  // Consume a sub-sub-section tag and size to shift the offset at the beginning
  // of the attribute list.
  data.GetULEB128(&offset);
  auto parent_section_length = data.GetU32(&offset);
  auto parent_section_end_offset = offset + parent_section_length;

  std::variant<uint64_t, llvm::StringRef> result;
  unsigned attribute_tag = 0;
  do {
    attribute_tag = data.GetULEB128(&offset);
    // From the riscv psABI document:
    // RISC-V attributes have a string value if the tag number is odd and an
    // integer value if the tag number is even.
    if (attribute_tag % 2)
      result = data.GetCStr(&offset);
    else
      result = data.GetULEB128(&offset);
  } while (attribute_tag != tag && offset < parent_section_end_offset);

  if (attribute_tag == tag)
    return result;

  return std::nullopt;
}

void ObjectFileELF::ParseRISCVAttributes(const DataExtractor &data,
                                         uint64_t length, ArchSpec &arch_spec) {
  Log *log = GetLog(LLDBLog::Modules);

  lldb::offset_t offset = 0;

  // According to the riscv psABI, the .riscv.attributes section has the
  // following hierarchical structure:
  //
  // Section:
  //   .riscv.attributes {
  //       - (uint8_t) format
  //       - Sub-Section 1 {
  //           * (uint32_t) length
  //           * (c_str) name
  //           * Sub-Sub-Section 1.1 {
  //               > (uleb128_t) tag
  //               > (uint32_t) length
  //               > (uleb128_t) attribute_tag_1.1.1
  //                   $ (c_str or uleb128_t) value
  //               > (uleb128_t) attribute_tag_1.1.2
  //                   $ (c_str or uleb128_t) value
  //               ...
  //               Other attributes...
  //               ...
  //               > (uleb128_t) attribute_tag_1.1.N
  //                   $ (c_str or uleb128_t) value
  //           }
  //           * Sub-Sub-Section 1.2 {
  //               ...
  //               Sub-Sub-Section structure...
  //               ...
  //           }
  //           ...
  //           Other sub-sub-sections...
  //           ...
  //       }
  //       - Sub-Section 2 {
  //           ...
  //           Sub-Section structure...
  //           ...
  //       }
  //       ...
  //       Other sub-sections...
  //       ...
  //   }

  uint8_t format_version = data.GetU8(&offset);
  if (format_version != llvm::ELFAttrs::Format_Version)
    return;

  auto subsection_or_opt =
      FindSubSectionOffsetByName(data, offset, length, "riscv");
  if (!subsection_or_opt) {
    LLDB_LOGF(log,
              "ObjectFileELF::%s Ill-formed .riscv.attributes section: "
              "mandatory 'riscv' sub-section was not preserved",
              __FUNCTION__);
    return;
  }

  auto subsubsection_or_opt = FindSubSubSectionOffsetByTag(
      data, *subsection_or_opt, llvm::ELFAttrs::File);
  if (!subsubsection_or_opt)
    return;

  auto value_or_opt = GetAttributeValueByTag(data, *subsubsection_or_opt,
                                             llvm::RISCVAttrs::ARCH);
  if (!value_or_opt)
    return;

  auto normalized_isa_info = llvm::RISCVISAInfo::parseNormalizedArchString(
      std::get<llvm::StringRef>(*value_or_opt));
  if (llvm::errorToBool(normalized_isa_info.takeError()))
    return;

  llvm::SubtargetFeatures features;
  features.addFeaturesVector((*normalized_isa_info)->toFeatures());
  arch_spec.SetSubtargetFeatures(std::move(features));

  // Additional verification of the arch string. This is primarily needed to
  // warn users if the executable file contains conflicting RISC-V extensions
  // that could lead to invalid disassembler output.
  auto isa_info = llvm::RISCVISAInfo::parseArchString(
      std::get<llvm::StringRef>(*value_or_opt),
      /* EnableExperimentalExtension=*/true);
  if (auto error = isa_info.takeError()) {
    StreamString ss;
    ss << "the .riscv.attributes section contains an invalid RISC-V arch "
          "string: "
       << llvm::toString(std::move(error))
       << "\n\tThis could result in misleading disassembler output\n";
    Debugger::ReportWarning(ss.GetString().str());
  }
}

// GetSectionHeaderInfo
size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
                                           DataExtractor &object_data,
                                           const elf::ELFHeader &header,
                                           lldb_private::UUID &uuid,
                                           std::string &gnu_debuglink_file,
                                           uint32_t &gnu_debuglink_crc,
                                           ArchSpec &arch_spec) {
  // Don't reparse the section headers if we already did that.
  if (!section_headers.empty())
    return section_headers.size();

  // Only initialize the arch_spec to okay defaults if they're not already set.
  // We'll refine this with note data as we parse the notes.
  if (arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS) {
    llvm::Triple::OSType ostype;
    llvm::Triple::OSType spec_ostype;
    const uint32_t sub_type = subTypeFromElfHeader(header);
    arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
                              header.e_ident[EI_OSABI]);

    // Validate if it is ok to remove GetOsFromOSABI. Note, that now the OS is
    // determined based on EI_OSABI flag and the info extracted from ELF notes
    // (see RefineModuleDetailsFromNote). However in some cases that still
    // might be not enough: for example a shared library might not have any
    // notes at all and have EI_OSABI flag set to System V, as result the OS
    // will be set to UnknownOS.
    GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
    spec_ostype = arch_spec.GetTriple().getOS();
    assert(spec_ostype == ostype);
    UNUSED_IF_ASSERT_DISABLED(spec_ostype);
  }

  if (arch_spec.GetMachine() == llvm::Triple::mips ||
      arch_spec.GetMachine() == llvm::Triple::mipsel ||
      arch_spec.GetMachine() == llvm::Triple::mips64 ||
      arch_spec.GetMachine() == llvm::Triple::mips64el) {
    switch (header.e_flags & llvm::ELF::EF_MIPS_ARCH_ASE) {
    case llvm::ELF::EF_MIPS_MICROMIPS:
      arch_spec.SetFlags(ArchSpec::eMIPSAse_micromips);
      break;
    case llvm::ELF::EF_MIPS_ARCH_ASE_M16:
      arch_spec.SetFlags(ArchSpec::eMIPSAse_mips16);
      break;
    case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX:
      arch_spec.SetFlags(ArchSpec::eMIPSAse_mdmx);
      break;
    default:
      break;
    }
  }

  if (arch_spec.GetMachine() == llvm::Triple::arm ||
      arch_spec.GetMachine() == llvm::Triple::thumb) {
    if (header.e_flags & llvm::ELF::EF_ARM_SOFT_FLOAT)
      arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
    else if (header.e_flags & llvm::ELF::EF_ARM_VFP_FLOAT)
      arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
  }

  if (arch_spec.GetMachine() == llvm::Triple::riscv32 ||
      arch_spec.GetMachine() == llvm::Triple::riscv64) {
    uint32_t flags = arch_spec.GetFlags();

    if (header.e_flags & llvm::ELF::EF_RISCV_RVC)
      flags |= ArchSpec::eRISCV_rvc;
    if (header.e_flags & llvm::ELF::EF_RISCV_RVE)
      flags |= ArchSpec::eRISCV_rve;

    if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_SINGLE) ==
        llvm::ELF::EF_RISCV_FLOAT_ABI_SINGLE)
      flags |= ArchSpec::eRISCV_float_abi_single;
    else if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_DOUBLE) ==
             llvm::ELF::EF_RISCV_FLOAT_ABI_DOUBLE)
      flags |= ArchSpec::eRISCV_float_abi_double;
    else if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_QUAD) ==
             llvm::ELF::EF_RISCV_FLOAT_ABI_QUAD)
      flags |= ArchSpec::eRISCV_float_abi_quad;

    arch_spec.SetFlags(flags);
  }

  if (arch_spec.GetMachine() == llvm::Triple::loongarch32 ||
      arch_spec.GetMachine() == llvm::Triple::loongarch64) {
    uint32_t flags = arch_spec.GetFlags();
    switch (header.e_flags & llvm::ELF::EF_LOONGARCH_ABI_MODIFIER_MASK) {
    case llvm::ELF::EF_LOONGARCH_ABI_SINGLE_FLOAT:
      flags |= ArchSpec::eLoongArch_abi_single_float;
      break;
    case llvm::ELF::EF_LOONGARCH_ABI_DOUBLE_FLOAT:
      flags |= ArchSpec::eLoongArch_abi_double_float;
      break;
    case llvm::ELF::EF_LOONGARCH_ABI_SOFT_FLOAT:
      break;
    }

    arch_spec.SetFlags(flags);
  }

  // If there are no section headers we are done.
  if (header.e_shnum == 0)
    return 0;

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

  section_headers.resize(header.e_shnum);
  if (section_headers.size() != header.e_shnum)
    return 0;

  const size_t sh_size = header.e_shnum * header.e_shentsize;
  const elf_off sh_offset = header.e_shoff;
  DataExtractor sh_data;
  if (sh_data.SetData(object_data, sh_offset, sh_size) != sh_size)
    return 0;

  uint32_t idx;
  lldb::offset_t offset;
  for (idx = 0, offset = 0; idx < header.e_shnum; ++idx) {
    if (!section_headers[idx].Parse(sh_data, &offset))
      break;
  }
  if (idx < section_headers.size())
    section_headers.resize(idx);

  const unsigned strtab_idx = header.e_shstrndx;
  if (strtab_idx && strtab_idx < section_headers.size()) {
    const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx];
    const size_t byte_size = sheader.sh_size;
    const Elf64_Off offset = sheader.sh_offset;
    lldb_private::DataExtractor shstr_data;

    if (shstr_data.SetData(object_data, offset, byte_size) == byte_size) {
      for (SectionHeaderCollIter I = section_headers.begin();
           I != section_headers.end(); ++I) {
        static constexpr llvm::StringLiteral g_sect_name_gnu_debuglink(
            ".gnu_debuglink");
        const ELFSectionHeaderInfo &sheader = *I;
        const uint64_t section_size =
            sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;
        llvm::StringRef name = shstr_data.PeekCStr(I->sh_name).value_or("");
        I->section_name = name.str();

        if (arch_spec.IsMIPS()) {
          uint32_t arch_flags = arch_spec.GetFlags();
          DataExtractor data;
          if (sheader.sh_type == SHT_MIPS_ABIFLAGS) {

            if (section_size && (data.SetData(object_data, sheader.sh_offset,
                                              section_size) == section_size)) {
              // MIPS ASE Mask is at offset 12 in MIPS.abiflags section
              lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0
              arch_flags |= data.GetU32(&offset);

              // The floating point ABI is at offset 7
              offset = 7;
              switch (data.GetU8(&offset)) {
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_ANY;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_DOUBLE;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SINGLE;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_OLD_64;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_XX;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_64:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64;
                break;
              case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A:
                arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64A;
                break;
              }
            }
          }
          // Settings appropriate ArchSpec ABI Flags
          switch (header.e_flags & llvm::ELF::EF_MIPS_ABI) {
          case llvm::ELF::EF_MIPS_ABI_O32:
            arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;
            break;
          case EF_MIPS_ABI_O64:
            arch_flags |= lldb_private::ArchSpec::eMIPSABI_O64;
            break;
          case EF_MIPS_ABI_EABI32:
            arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI32;
            break;
          case EF_MIPS_ABI_EABI64:
            arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI64;
            break;
          default:
            // ABI Mask doesn't cover N32 and N64 ABI.
            if (header.e_ident[EI_CLASS] == llvm::ELF::ELFCLASS64)
              arch_flags |= lldb_private::ArchSpec::eMIPSABI_N64;
            else if (header.e_flags & llvm::ELF::EF_MIPS_ABI2)
              arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32;
            break;
          }
          arch_spec.SetFlags(arch_flags);
        }

        if (arch_spec.GetMachine() == llvm::Triple::arm ||
            arch_spec.GetMachine() == llvm::Triple::thumb) {
          DataExtractor data;

          if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
              data.SetData(object_data, sheader.sh_offset, section_size) == section_size)
            ParseARMAttributes(data, section_size, arch_spec);
        }

        if (arch_spec.GetTriple().isRISCV()) {
          DataExtractor data;
          if (sheader.sh_type == llvm::ELF::SHT_RISCV_ATTRIBUTES &&
              section_size != 0 &&
              data.SetData(object_data, sheader.sh_offset, section_size) ==
                  section_size)
            ParseRISCVAttributes(data, section_size, arch_spec);
        }

        if (name == g_sect_name_gnu_debuglink) {
          DataExtractor data;
          if (section_size && (data.SetData(object_data, sheader.sh_offset,
                                            section_size) == section_size)) {
            lldb::offset_t gnu_debuglink_offset = 0;
            gnu_debuglink_file = data.GetCStr(&gnu_debuglink_offset);
            gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4);
            data.GetU32(&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
          }
        }

        // Process ELF note section entries.
        bool is_note_header = (sheader.sh_type == SHT_NOTE);

        // The section header ".note.android.ident" is stored as a
        // PROGBITS type header but it is actually a note header.
        static constexpr llvm::StringLiteral g_sect_name_android_ident(
            ".note.android.ident");
        if (!is_note_header && name == g_sect_name_android_ident)
          is_note_header = true;

        if (is_note_header) {
          // Allow notes to refine module info.
          DataExtractor data;
          if (section_size && (data.SetData(object_data, sheader.sh_offset,
                                            section_size) == section_size)) {
            Status error = RefineModuleDetailsFromNote(data, arch_spec, uuid);
            if (error.Fail()) {
              LLDB_LOGF(log, "ObjectFileELF::%s ELF note processing failed: %s",
                        __FUNCTION__, error.AsCString());
            }
          }
        }
      }

      // Make any unknown triple components to be unspecified unknowns.
      if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
        arch_spec.GetTriple().setVendorName(llvm::StringRef());
      if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS)
        arch_spec.GetTriple().setOSName(llvm::StringRef());

      return section_headers.size();
    }
  }

  section_headers.clear();
  return 0;
}

llvm::StringRef
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
  size_t pos = symbol_name.find('@');
  return symbol_name.substr(0, pos);
}

// ParseSectionHeaders
size_t ObjectFileELF::ParseSectionHeaders() {
  return GetSectionHeaderInfo(m_section_headers, *m_data_nsp, m_header, m_uuid,
                              m_gnu_debuglink_file, m_gnu_debuglink_crc,
                              m_arch_spec);
}

const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
  if (!ParseSectionHeaders())
    return nullptr;

  if (id < m_section_headers.size())
    return &m_section_headers[id];

  return nullptr;
}

lldb::user_id_t ObjectFileELF::GetSectionIndexByName(llvm::StringRef name) {
  if (name.empty() || !ParseSectionHeaders())
    return 0;
  for (size_t i = 1; i < m_section_headers.size(); ++i)
    if (m_section_headers[i].section_name == name)
      return i;
  return 0;
}

static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
  if (Name.consume_front(".debug_"))
    return ObjectFile::GetDWARFSectionTypeFromName(Name);

  return llvm::StringSwitch<SectionType>(Name)
      .Case(".ARM.exidx", eSectionTypeARMexidx)
      .Case(".ARM.extab", eSectionTypeARMextab)
      .Case(".ctf", eSectionTypeDebug)
      .Cases({".data", ".tdata"}, eSectionTypeData)
      .Case(".eh_frame", eSectionTypeEHFrame)
      .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
      .Case(".gosymtab", eSectionTypeGoSymtab)
      .Case(".text", eSectionTypeCode)
      .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
      .Case(".lldbformatters", lldb::eSectionTypeLLDBFormatters)
      .Case(".swift_ast", eSectionTypeSwiftModules)
      .Default(eSectionTypeOther);
}

SectionType ObjectFileELF::GetSectionType(const ELFSectionHeaderInfo &H) const {
  switch (H.sh_type) {
  case SHT_PROGBITS:
    if (H.sh_flags & SHF_EXECINSTR)
      return eSectionTypeCode;
    break;
  case SHT_NOBITS:
    if (H.sh_flags & SHF_ALLOC)
      return eSectionTypeZeroFill;
    break;
  case SHT_SYMTAB:
    return eSectionTypeELFSymbolTable;
  case SHT_DYNSYM:
    return eSectionTypeELFDynamicSymbols;
  case SHT_RELA:
  case SHT_REL:
    return eSectionTypeELFRelocationEntries;
  case SHT_DYNAMIC:
    return eSectionTypeELFDynamicLinkInfo;
  }
  return GetSectionTypeFromName(H.section_name);
}

static Permissions GetPermissions(const ELFSectionHeader &H) {
  Permissions Perm = Permissions(0);
  if (H.sh_flags & SHF_ALLOC)
    Perm |= ePermissionsReadable;
  if (H.sh_flags & SHF_WRITE)
    Perm |= ePermissionsWritable;
  if (H.sh_flags & SHF_EXECINSTR)
    Perm |= ePermissionsExecutable;
  return Perm;
}

static Permissions GetPermissions(const ELFProgramHeader &H) {
  Permissions Perm = Permissions(0);
  if (H.p_flags & PF_R)
    Perm |= ePermissionsReadable;
  if (H.p_flags & PF_W)
    Perm |= ePermissionsWritable;
  if (H.p_flags & PF_X)
    Perm |= ePermissionsExecutable;
  return Perm;
}

namespace {

using VMRange = lldb_private::Range<addr_t, addr_t>;

struct SectionAddressInfo {
  SectionSP Segment;
  VMRange Range;
};

// (Unlinked) ELF object files usually have 0 for every section address, meaning
// we need to compute synthetic addresses in order for "file addresses" from
// different sections to not overlap. This class handles that logic.
class VMAddressProvider {
  using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
                                       llvm::IntervalMapHalfOpenInfo<addr_t>>;

  ObjectFile::Type ObjectType;
  addr_t NextVMAddress = 0;
  VMMap::Allocator Alloc;
  VMMap Segments{Alloc};
  VMMap Sections{Alloc};
  lldb_private::Log *Log = GetLog(LLDBLog::Modules);
  size_t SegmentCount = 0;
  std::string SegmentName;

  VMRange GetVMRange(const ELFSectionHeader &H) {
    addr_t Address = H.sh_addr;
    addr_t Size = H.sh_flags & SHF_ALLOC ? H.sh_size : 0;

    // When this is a debug file for relocatable file, the address is all zero
    // and thus needs to use accumulate method
    if ((ObjectType == ObjectFile::Type::eTypeObjectFile ||
         (ObjectType == ObjectFile::Type::eTypeDebugInfo && H.sh_addr == 0)) &&
        Segments.empty() && (H.sh_flags & SHF_ALLOC)) {
      NextVMAddress =
          llvm::alignTo(NextVMAddress, std::max<addr_t>(H.sh_addralign, 1));
      Address = NextVMAddress;
      NextVMAddress += Size;
    }
    return VMRange(Address, Size);
  }

public:
  VMAddressProvider(ObjectFile::Type Type, llvm::StringRef SegmentName)
      : ObjectType(Type), SegmentName(std::string(SegmentName)) {}

  std::string GetNextSegmentName() const {
    return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str();
  }

  std::optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) {
    if (H.p_memsz == 0) {
      LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?",
               SegmentName);
      return std::nullopt;
    }

    if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) {
      LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?",
               SegmentName);
      return std::nullopt;
    }
    return VMRange(H.p_vaddr, H.p_memsz);
  }

  std::optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) {
    VMRange Range = GetVMRange(H);
    SectionSP Segment;
    auto It = Segments.find(Range.GetRangeBase());
    if ((H.sh_flags & SHF_ALLOC) && It.valid()) {
      addr_t MaxSize;
      if (It.start() <= Range.GetRangeBase()) {
        MaxSize = It.stop() - Range.GetRangeBase();
        Segment = *It;
      } else
        MaxSize = It.start() - Range.GetRangeBase();
      if (Range.GetByteSize() > MaxSize) {
        LLDB_LOG(Log, "Shortening section crossing segment boundaries. "
                      "Corrupt object file?");
        Range.SetByteSize(MaxSize);
      }
    }
    if (Range.GetByteSize() > 0 &&
        Sections.overlaps(Range.GetRangeBase(), Range.GetRangeEnd())) {
      LLDB_LOG(Log, "Ignoring overlapping section. Corrupt object file?");
      return std::nullopt;
    }
    if (Segment)
      Range.Slide(-Segment->GetFileAddress());
    return SectionAddressInfo{Segment, Range};
  }

  void AddSegment(const VMRange &Range, SectionSP Seg) {
    Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg));
    ++SegmentCount;
  }

  void AddSection(SectionAddressInfo Info, SectionSP Sect) {
    if (Info.Range.GetByteSize() == 0)
      return;
    if (Info.Segment)
      Info.Range.Slide(Info.Segment->GetFileAddress());
    Sections.insert(Info.Range.GetRangeBase(), Info.Range.GetRangeEnd(),
                    std::move(Sect));
  }
};
}

// We have to do this because ELF doesn't have section IDs, and also
// doesn't require section names to be unique.  (We use the section index
// for section IDs, but that isn't guaranteed to be the same in separate
// debug images.)
static SectionSP FindMatchingSection(const SectionList &section_list,
                                     SectionSP section) {
  SectionSP sect_sp;

  addr_t vm_addr = section->GetFileAddress();
  llvm::StringRef name = section->GetName();
  offset_t byte_size = section->GetByteSize();
  bool thread_specific = section->IsThreadSpecific();
  uint32_t permissions = section->GetPermissions();
  uint32_t alignment = section->GetLog2Align();

  for (auto sect : section_list) {
    if (sect->GetName() == name &&
        sect->IsThreadSpecific() == thread_specific &&
        sect->GetPermissions() == permissions &&
        sect->GetByteSize() == byte_size && sect->GetFileAddress() == vm_addr &&
        sect->GetLog2Align() == alignment) {
      sect_sp = sect;
      break;
    } else {
      sect_sp = FindMatchingSection(sect->GetChildren(), section);
      if (sect_sp)
        break;
    }
  }

  return sect_sp;
}

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

  m_sections_up = std::make_unique<SectionList>();
  VMAddressProvider regular_provider(GetType(), "PT_LOAD");
  VMAddressProvider tls_provider(GetType(), "PT_TLS");

  for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
    const ELFProgramHeader &PHdr = EnumPHdr.value();
    if (PHdr.p_type != PT_LOAD && PHdr.p_type != PT_TLS)
      continue;

    VMAddressProvider &provider =
        PHdr.p_type == PT_TLS ? tls_provider : regular_provider;
    auto InfoOr = provider.GetAddressInfo(PHdr);
    if (!InfoOr)
      continue;

    uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1));
    SectionSP Segment = std::make_shared<Section>(
        GetModule(), this, SegmentID(EnumPHdr.index()),
        provider.GetNextSegmentName(), eSectionTypeContainer,
        InfoOr->GetRangeBase(), InfoOr->GetByteSize(), PHdr.p_offset,
        PHdr.p_filesz, Log2Align, /*flags*/ 0);
    Segment->SetPermissions(GetPermissions(PHdr));
    Segment->SetIsThreadSpecific(PHdr.p_type == PT_TLS);
    m_sections_up->AddSection(Segment);

    provider.AddSegment(*InfoOr, std::move(Segment));
  }

  ParseSectionHeaders();
  if (m_section_headers.empty())
    return;

  for (SectionHeaderCollIter I = std::next(m_section_headers.begin());
       I != m_section_headers.end(); ++I) {
    const ELFSectionHeaderInfo &header = *I;

    const std::string &name = I->section_name;
    const uint64_t file_size =
        header.sh_type == SHT_NOBITS ? 0 : header.sh_size;

    VMAddressProvider &provider =
        header.sh_flags & SHF_TLS ? tls_provider : regular_provider;
    auto InfoOr = provider.GetAddressInfo(header);
    if (!InfoOr)
      continue;

    SectionType sect_type = GetSectionType(header);

    elf::elf_xword log2align =
        (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);

    SectionSP section_sp = std::make_shared<Section>(
        InfoOr->Segment, GetModule(), // Module to which this section belongs.
        this,            // ObjectFile to which this section belongs and should
                         // read section data from.
        SectionIndex(I), // Section ID.
        name,            // Section name.
        sect_type,       // Section type.
        InfoOr->Range.GetRangeBase(), // VM address.
        InfoOr->Range.GetByteSize(),  // VM size in bytes of this section.
        header.sh_offset,             // Offset of this section in the file.
        file_size,        // Size of the section as found in the file.
        log2align,        // Alignment of the section
        header.sh_flags); // Flags for this section.

    section_sp->SetPermissions(GetPermissions(header));
    section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS);
    (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_up)
        .AddSection(section_sp);
    provider.AddSection(std::move(*InfoOr), std::move(section_sp));
  }

  // Merge the two adding any new sections, and overwriting any existing
  // sections that are SHT_NOBITS
  unified_section_list =
      SectionList::Merge(unified_section_list, *m_sections_up, MergeSections);

  // If there's a .gnu_debugdata section, we'll try to read the .symtab that's
  // embedded in there and replace the one in the original object file (if any).
  // If there's none in the orignal object file, we add it to it.
  if (auto gdd_obj_file = GetGnuDebugDataObjectFile()) {
    if (auto gdd_objfile_section_list = gdd_obj_file->GetSectionList()) {
      if (SectionSP symtab_section_sp =
              gdd_objfile_section_list->FindSectionByType(
                  eSectionTypeELFSymbolTable, true)) {
        SectionSP module_section_sp = unified_section_list.FindSectionByType(
            eSectionTypeELFSymbolTable, true);
        if (module_section_sp)
          unified_section_list.ReplaceSection(module_section_sp,
                                              symtab_section_sp);
        else
          unified_section_list.AddSection(symtab_section_sp);
      }
    }
  }
}

std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() {
  if (m_gnu_debug_data_object_file != nullptr)
    return m_gnu_debug_data_object_file;

  SectionSP section = GetSectionList()->FindSectionByName(".gnu_debugdata");
  if (!section)
    return nullptr;

  if (!llvm::compression::xz::isAvailable()) {
    GetModule()->ReportWarning(
        "no LZMA support found for reading .gnu_debugdata section");
    return nullptr;
  }

  // Uncompress the data
  DataExtractor data;
  section->GetSectionData(data);
  llvm::SmallVector<uint8_t, 0> uncompressedData;
  auto err =
      llvm::compression::xz::decompress(data.GetData(), uncompressedData);
  if (err) {
    GetModule()->ReportWarning(
        "an error occurred while decompressing the section {0}: {1}",
        section->GetName(), llvm::toString(std::move(err)).c_str());
    return nullptr;
  }

  // Construct ObjectFileELF object from decompressed buffer
  DataBufferSP gdd_data_buf(
      new DataBufferHeap(uncompressedData.data(), uncompressedData.size()));
  DataExtractorSP extractor_sp = std::make_shared<DataExtractor>(gdd_data_buf);
  auto fspec = GetFileSpec().CopyByAppendingPathComponent(
      llvm::StringRef("gnu_debugdata"));
  m_gnu_debug_data_object_file.reset(new ObjectFileELF(
      GetModule(), extractor_sp, 0, &fspec, 0, gdd_data_buf->GetByteSize()));

  // This line is essential; otherwise a breakpoint can be set but not hit.
  m_gnu_debug_data_object_file->SetType(ObjectFile::eTypeDebugInfo);

  ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture();
  if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec))
    return m_gnu_debug_data_object_file;

  return nullptr;
}

// Find the arm/aarch64 mapping symbol character in the given symbol name.
// Mapping symbols have the form of "$<char>[.<any>]*". Additionally we
// recognize cases when the mapping symbol prefixed by an arbitrary string
// because if a symbol prefix added to each symbol in the object file with
// objcopy then the mapping symbols are also prefixed.
static char FindArmAarch64MappingSymbol(llvm::StringRef symbol_name) {
  size_t dollar_pos = symbol_name.find('$');
  if (dollar_pos == llvm::StringRef::npos)
    return '\0';

  llvm::StringRef mapping = symbol_name.drop_front(dollar_pos + 1);
  if (mapping.empty())
    return '\0';

  if (mapping.size() == 1 || mapping[1] == '.')
    return mapping[0];
  return '\0';
}

static char FindRISCVMappingSymbol(llvm::StringRef symbol_name) {
  if (symbol_name == "$d")
    return 'd';
  if (symbol_name == "$x")
    return 'x';
  return '\0';
}

#define STO_MIPS_ISA (3 << 6)
#define STO_MICROMIPS (2 << 6)
#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)

// private
std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
                            SectionList *section_list, const size_t num_symbols,
                            const DataExtractor &symtab_data,
                            const DataExtractor &strtab_data) {
  ELFSymbol symbol;
  lldb::offset_t offset = 0;
  // The changes these symbols would make to the class map. We will also update
  // m_address_class_map but need to tell the caller what changed because the
  // caller may be another object file.
  FileAddressToAddressClassMap address_class_map;

  static constexpr llvm::StringLiteral text_section_name(".text");
  static constexpr llvm::StringLiteral init_section_name(".init");
  static constexpr llvm::StringLiteral fini_section_name(".fini");
  static constexpr llvm::StringLiteral ctors_section_name(".ctors");
  static constexpr llvm::StringLiteral dtors_section_name(".dtors");

  static constexpr llvm::StringLiteral data_section_name(".data");
  static constexpr llvm::StringLiteral rodata_section_name(".rodata");
  static constexpr llvm::StringLiteral rodata1_section_name(".rodata1");
  static constexpr llvm::StringLiteral data2_section_name(".data1");
  static constexpr llvm::StringLiteral bss_section_name(".bss");

  // On Android the oatdata and the oatexec symbols in the oat and odex files
  // covers the full .text section what causes issues with displaying unusable
  // symbol name to the user and very slow unwinding speed because the
  // instruction emulation based unwind plans try to emulate all instructions
  // in these symbols. Don't add these symbols to the symbol list as they have
  // no use for the debugger and they are causing a lot of trouble. Filtering
  // can't be restricted to Android because this special object file don't
  // contain the note section specifying the environment to Android but the
  // custom extension and file name makes it highly unlikely that this will
  // collide with anything else.
  llvm::StringRef file_extension = m_file.GetFileNameExtension();
  bool skip_oatdata_oatexec =
      file_extension == ".oat" || file_extension == ".odex";

  ArchSpec arch = GetArchitecture();
  ModuleSP module_sp(GetModule());
  SectionList *module_section_list =
      module_sp ? module_sp->GetSectionList() : nullptr;

  // We might have debug information in a separate object, in which case
  // we need to map the sections from that object to the sections in the
  // main object during symbol lookup.  If we had to compare the sections
  // for every single symbol, that would be expensive, so this map is
  // used to accelerate the process.
  std::unordered_map<lldb::SectionSP, lldb::SectionSP> section_map;

  unsigned i;
  for (i = 0; i < num_symbols; ++i) {
    if (!symbol.Parse(symtab_data, &offset))
      break;

    // A missing or unterminated name reads as empty.
    llvm::StringRef symbol_name =
        strtab_data.PeekCStr(symbol.st_name).value_or("");

    // Skip local symbols starting with ".L" because these are compiler
    // generated local labels used for internal purposes (e.g. debugging,
    // optimization) and are not relevant for symbol resolution or external
    // linkage.
    if (symbol_name.starts_with(".L"))
      continue;

    // The mold linker emits an extra function symbol like "foo$plt" in
    // .symtab/.dynsym that overlaps the PLT stub which ParsePLTRelocations
    // will synthesize as an eSymbolTypeTrampoline named "foo". Drop the
    // redundant sibling here so the finalized symbol table has a single
    // clean entry per PLT function.
    if (symbol.getType() == STT_FUNC && symbol_name.ends_with("$plt"))
      continue;

    // No need to add non-section symbols that have no names
    if (symbol.getType() != STT_SECTION && symbol_name.empty())
      continue;

    // Skipping oatdata and oatexec sections if it is requested. See details
    // above the definition of skip_oatdata_oatexec for the reasons.
    if (skip_oatdata_oatexec &&
        (symbol_name == "oatdata" || symbol_name == "oatexec"))
      continue;

    SectionSP symbol_section_sp;
    SymbolType symbol_type = eSymbolTypeInvalid;
    Elf64_Half shndx = symbol.st_shndx;

    switch (shndx) {
    case SHN_ABS:
      symbol_type = eSymbolTypeAbsolute;
      break;
    case SHN_UNDEF:
      symbol_type = eSymbolTypeUndefined;
      break;
    default:
      symbol_section_sp = section_list->FindSectionByID(shndx);
      break;
    }

    // If a symbol is undefined do not process it further even if it has a STT
    // type
    if (symbol_type != eSymbolTypeUndefined) {
      switch (symbol.getType()) {
      default:
      case STT_NOTYPE:
        // The symbol's type is not specified.
        break;

      case STT_OBJECT:
        // The symbol is associated with a data object, such as a variable, an
        // array, etc.
        symbol_type = eSymbolTypeData;
        break;

      case STT_FUNC:
        // The symbol is associated with a function or other executable code.
        symbol_type = eSymbolTypeCode;
        break;

      case STT_SECTION:
        // The symbol is associated with a section. Symbol table entries of
        // this type exist primarily for relocation and normally have STB_LOCAL
        // binding.
        break;

      case STT_FILE:
        // Conventionally, the symbol's name gives the name of the source file
        // associated with the object file. A file symbol has STB_LOCAL
        // binding, its section index is SHN_ABS, and it precedes the other
        // STB_LOCAL symbols for the file, if it is present.
        symbol_type = eSymbolTypeSourceFile;
        break;

      case STT_GNU_IFUNC:
        // The symbol is associated with an indirect function. The actual
        // function will be resolved if it is referenced.
        symbol_type = eSymbolTypeResolver;
        break;

      case STT_TLS:
        // The symbol is associated with a thread-local data object, such as
        // a thread-local variable.
        symbol_type = eSymbolTypeData;
        break;
      }
    }

    if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION) {
      if (symbol_section_sp) {
        llvm::StringRef sect_name = symbol_section_sp->GetName();
        if (sect_name == text_section_name || sect_name == init_section_name ||
            sect_name == fini_section_name || sect_name == ctors_section_name ||
            sect_name == dtors_section_name) {
          symbol_type = eSymbolTypeCode;
        } else if (sect_name == data_section_name ||
                   sect_name == data2_section_name ||
                   sect_name == rodata_section_name ||
                   sect_name == rodata1_section_name ||
                   sect_name == bss_section_name) {
          symbol_type = eSymbolTypeData;
        } else if (symbol_section_sp->Get() & SHF_ALLOC)
          // Check for symbols from custom sections (e.g. added by linker
          // scripts) with SHF_ALLOC (i.e. occupies memory during process
          // execution) in their flags.
          symbol_type = eSymbolTypeData;
      }
    }

    int64_t symbol_value_offset = 0;
    uint32_t additional_flags = 0;
    if (arch.IsValid()) {
      if (arch.GetMachine() == llvm::Triple::arm) {
        if (symbol.getBinding() == STB_LOCAL) {
          char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
          if (symbol_type == eSymbolTypeCode) {
            switch (mapping_symbol) {
            case 'a':
              // $a[.<any>]* - marks an ARM instruction sequence
              address_class_map[symbol.st_value] = AddressClass::eCode;
              break;
            case 'b':
            case 't':
              // $b[.<any>]* - marks a THUMB BL instruction sequence
              // $t[.<any>]* - marks a THUMB instruction sequence
              address_class_map[symbol.st_value] =
                  AddressClass::eCodeAlternateISA;
              break;
            case 'd':
              // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
              address_class_map[symbol.st_value] = AddressClass::eData;
              break;
            }
          }
          if (mapping_symbol)
            continue;
        }
      } else if (arch.GetMachine() == llvm::Triple::aarch64) {
        if (symbol.getBinding() == STB_LOCAL) {
          char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
          if (symbol_type == eSymbolTypeCode) {
            switch (mapping_symbol) {
            case 'x':
              // $x[.<any>]* - marks an A64 instruction sequence
              address_class_map[symbol.st_value] = AddressClass::eCode;
              break;
            case 'd':
              // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
              address_class_map[symbol.st_value] = AddressClass::eData;
              break;
            }
          }
          if (mapping_symbol)
            continue;
        }
      } else if (arch.GetTriple().isRISCV()) {
        if (symbol.getBinding() == STB_LOCAL) {
          char mapping_symbol = FindRISCVMappingSymbol(symbol_name);
          if (symbol_type == eSymbolTypeCode) {
            // Only handle $d and $x mapping symbols.
            // Other mapping symbols are ignored as they don't affect address
            // classification.
            switch (mapping_symbol) {
            case 'x':
              // $x - marks a RISCV instruction sequence
              address_class_map[symbol.st_value] = AddressClass::eCode;
              break;
            case 'd':
              // $d - marks a RISCV data item sequence
              address_class_map[symbol.st_value] = AddressClass::eData;
              break;
            }
          }
          if (mapping_symbol)
            continue;
        }
      }

      if (arch.GetMachine() == llvm::Triple::arm) {
        if (symbol_type == eSymbolTypeCode) {
          if (symbol.st_value & 1) {
            // Subtracting 1 from the address effectively unsets the low order
            // bit, which results in the address actually pointing to the
            // beginning of the symbol. This delta will be used below in
            // conjunction with symbol.st_value to produce the final
            // symbol_value that we store in the symtab.
            symbol_value_offset = -1;
            address_class_map[symbol.st_value ^ 1] =
                AddressClass::eCodeAlternateISA;
          } else {
            // This address is ARM
            address_class_map[symbol.st_value] = AddressClass::eCode;
          }
        }
      }

      /*
       * MIPS:
       * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for
       * MIPS).
       * This allows processor to switch between microMIPS and MIPS without any
       * need
       * for special mode-control register. However, apart from .debug_line,
       * none of
       * the ELF/DWARF sections set the ISA bit (for symbol or section). Use
       * st_other
       * flag to check whether the symbol is microMIPS and then set the address
       * class
       * accordingly.
      */
      if (arch.IsMIPS()) {
        if (IS_MICROMIPS(symbol.st_other))
          address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
        else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
          symbol.st_value = symbol.st_value & (~1ull);
          address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
        } else {
          if (symbol_type == eSymbolTypeCode)
            address_class_map[symbol.st_value] = AddressClass::eCode;
          else if (symbol_type == eSymbolTypeData)
            address_class_map[symbol.st_value] = AddressClass::eData;
          else
            address_class_map[symbol.st_value] = AddressClass::eUnknown;
        }
      }
    }

    // symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB
    // symbols. See above for more details.
    uint64_t symbol_value = symbol.st_value + symbol_value_offset;

    if (symbol_section_sp &&
        CalculateType() != ObjectFile::Type::eTypeObjectFile)
      symbol_value -= symbol_section_sp->GetFileAddress();

    if (symbol_section_sp && module_section_list &&
        module_section_list != section_list) {
      auto section_it = section_map.find(symbol_section_sp);
      if (section_it == section_map.end()) {
        section_it = section_map
                         .emplace(symbol_section_sp,
                                  FindMatchingSection(*module_section_list,
                                                      symbol_section_sp))
                         .first;
      }
      if (section_it->second)
        symbol_section_sp = section_it->second;
    }

    bool is_global = symbol.getBinding() == STB_GLOBAL;
    uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;

    // Symbol names may contain @VERSION suffixes. Find those and strip them
    // temporarily.
    size_t version_pos = symbol_name.find('@');
    bool has_suffix = version_pos != llvm::StringRef::npos;
    llvm::StringRef symbol_bare = symbol_name.substr(0, version_pos);
    Mangled mangled(symbol_bare);

    // Now append the suffix back to mangled and unmangled names. Only do it if
    // the demangling was successful (string is not empty).
    if (has_suffix) {
      llvm::StringRef suffix = symbol_name.substr(version_pos);

      llvm::StringRef mangled_name = mangled.GetMangledName().GetStringRef();
      if (!mangled_name.empty())
        mangled.SetMangledName(ConstString((mangled_name + suffix).str()));

      ConstString demangled = mangled.GetDemangledName();
      llvm::StringRef demangled_name = demangled.GetStringRef();
      if (!demangled_name.empty())
        mangled.SetDemangledName(ConstString((demangled_name + suffix).str()));
    }

    // In ELF all symbol should have a valid size but it is not true for some
    // function symbols coming from hand written assembly. As none of the
    // function symbol should have 0 size we try to calculate the size for
    // these symbols in the symtab with saying that their original size is not
    // valid.
    bool symbol_size_valid =
        symbol.st_size != 0 || symbol.getType() != STT_FUNC;

    bool is_trampoline = false;
    if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64)) {
      // On AArch64, trampolines are registered as code.
      // If we detect a trampoline (which starts with __AArch64ADRPThunk_ or
      // __AArch64AbsLongThunk_) we register the symbol as a trampoline. This
      // way we will be able to detect the trampoline when we step in a function
      // and step through the trampoline.
      if (symbol_type == eSymbolTypeCode) {
        llvm::StringRef trampoline_name = mangled.GetName().GetStringRef();
        if (trampoline_name.starts_with("__AArch64ADRPThunk_") ||
            trampoline_name.starts_with("__AArch64AbsLongThunk_")) {
          symbol_type = eSymbolTypeTrampoline;
          is_trampoline = true;
        }
      }
    }

    Symbol dc_symbol(
        i + start_id, // ID is the original symbol table index.
        mangled,
        symbol_type,                    // Type of this symbol
        is_global,                      // Is this globally visible?
        false,                          // Is this symbol debug info?
        is_trampoline,                  // Is this symbol a trampoline?
        false,                          // Is this symbol artificial?
        AddressRange(symbol_section_sp, // Section in which this symbol is
                                        // defined or null.
                     symbol_value,      // Offset in section or symbol value.
                     symbol.st_size),   // Size in bytes of this symbol.
        symbol_size_valid,              // Symbol size is valid
        has_suffix,                     // Contains linker annotations?
        flags);                         // Symbol flags.
    if (symbol.getBinding() == STB_WEAK)
      dc_symbol.SetIsWeak(true);
    symtab->AddSymbol(dc_symbol);
  }

  m_address_class_map.merge(address_class_map);
  return {i, address_class_map};
}

std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id,
                                lldb_private::Section *symtab) {
  if (symtab->GetObjectFile() != this) {
    // If the symbol table section is owned by a different object file, have it
    // do the parsing.
    ObjectFileELF *obj_file_elf =
        static_cast<ObjectFileELF *>(symtab->GetObjectFile());
    auto [num_symbols, address_class_map] =
        obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);

    // The other object file returned the changes it made to its address
    // class map, make the same changes to ours.
    m_address_class_map.merge(address_class_map);

    return {num_symbols, address_class_map};
  }

  // Get section list for this object file.
  SectionList *section_list = m_sections_up.get();
  if (!section_list)
    return {};

  user_id_t symtab_id = symtab->GetID();
  const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
  assert(symtab_hdr->sh_type == SHT_SYMTAB ||
         symtab_hdr->sh_type == SHT_DYNSYM);

  // sh_link: section header index of associated string table.
  user_id_t strtab_id = symtab_hdr->sh_link;
  Section *strtab = section_list->FindSectionByID(strtab_id).get();

  if (symtab && strtab) {
    assert(symtab->GetObjectFile() == this);
    assert(strtab->GetObjectFile() == this);

    DataExtractor symtab_data;
    DataExtractor strtab_data;
    if (ReadSectionData(symtab, symtab_data) &&
        ReadSectionData(strtab, strtab_data)) {
      size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;

      return ParseSymbols(symbol_table, start_id, section_list, num_symbols,
                          symtab_data, strtab_data);
    }
  }

  return {0, {}};
}

size_t ObjectFileELF::ParseDynamicSymbols() {
  if (m_dynamic_symbols.size())
    return m_dynamic_symbols.size();

  std::optional<DataExtractor> dynamic_data = GetDynamicData();
  if (!dynamic_data)
    return 0;

  ELFDynamicWithName e;
  lldb::offset_t cursor = 0;
  while (e.symbol.Parse(*dynamic_data, &cursor)) {
    m_dynamic_symbols.push_back(e);
    if (e.symbol.d_tag == DT_NULL)
      break;
  }
  if (std::optional<DataExtractor> dynstr_data = GetDynstrData()) {
    for (ELFDynamicWithName &entry : m_dynamic_symbols) {
      switch (entry.symbol.d_tag) {
      case DT_NEEDED:
      case DT_SONAME:
      case DT_RPATH:
      case DT_RUNPATH:
      case DT_AUXILIARY:
      case DT_FILTER: {
        lldb::offset_t cursor = entry.symbol.d_val;
        const char *name = dynstr_data->GetCStr(&cursor);
        if (name)
          entry.name = std::string(name);
        break;
      }
      default:
        break;
      }
    }
  }
  return m_dynamic_symbols.size();
}

const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) {
  if (!ParseDynamicSymbols())
    return nullptr;
  for (const auto &entry : m_dynamic_symbols) {
    if (entry.symbol.d_tag == tag)
      return &entry.symbol;
  }
  return nullptr;
}

unsigned ObjectFileELF::PLTRelocationType() {
  // DT_PLTREL
  //  This member specifies the type of relocation entry to which the
  //  procedure linkage table refers. The d_val member holds DT_REL or
  //  DT_RELA, as appropriate. All relocations in a procedure linkage table
  //  must use the same relocation.
  const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);

  if (symbol)
    return symbol->d_val;

  return 0;
}

// Returns the size of the normal plt entries and the offset of the first
// normal plt entry. The 0th entry in the plt table is usually a resolution
// entry which have different size in some architectures then the rest of the
// plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
                         const ELFSectionHeader *plt_hdr) {
  const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;

  // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are
  // 16 bytes. So round the entsize up by the alignment if addralign is set.
  elf_xword plt_entsize =
      plt_hdr->sh_addralign
          ? llvm::alignTo(plt_hdr->sh_entsize, plt_hdr->sh_addralign)
          : plt_hdr->sh_entsize;

  // Some linkers e.g ld for arm, fill plt_hdr->sh_entsize field incorrectly.
  // PLT entries relocation code in general requires multiple instruction and
  // should be greater than 4 bytes in most cases. Try to guess correct size
  // just in case.
  if (plt_entsize <= 4) {
    // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the
    // size of the plt entries based on the number of entries and the size of
    // the plt section with the assumption that the size of the 0th entry is at
    // least as big as the size of the normal entries and it isn't much bigger
    // then that.
    if (plt_hdr->sh_addralign)
      plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign /
                    (num_relocations + 1) * plt_hdr->sh_addralign;
    else
      plt_entsize = plt_hdr->sh_size / (num_relocations + 1);
  }

  elf_xword plt_offset = plt_hdr->sh_size - num_relocations * plt_entsize;

  return std::make_pair(plt_entsize, plt_offset);
}

static unsigned ParsePLTRelocations(
    Symtab *symbol_table, user_id_t start_id, unsigned rel_type,
    const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
    const ELFSectionHeader *plt_hdr, const ELFSectionHeader *sym_hdr,
    const lldb::SectionSP &plt_section_sp, DataExtractor &rel_data,
    DataExtractor &symtab_data, DataExtractor &strtab_data) {
  ELFRelocation rel(rel_type);
  ELFSymbol symbol;
  lldb::offset_t offset = 0;

  uint64_t plt_offset, plt_entsize;
  std::tie(plt_entsize, plt_offset) =
      GetPltEntrySizeAndOffset(rel_hdr, plt_hdr);
  const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;

  typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
  reloc_info_fn reloc_type;
  reloc_info_fn reloc_symbol;

  if (hdr->Is32Bit()) {
    reloc_type = ELFRelocation::RelocType32;
    reloc_symbol = ELFRelocation::RelocSymbol32;
  } else {
    reloc_type = ELFRelocation::RelocType64;
    reloc_symbol = ELFRelocation::RelocSymbol64;
  }

  unsigned slot_type = hdr->GetRelocationJumpSlotType();
  unsigned i;
  for (i = 0; i < num_relocations; ++i) {
    if (!rel.Parse(rel_data, &offset))
      break;

    if (reloc_type(rel) != slot_type)
      continue;

    lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
    if (!symbol.Parse(symtab_data, &symbol_offset))
      break;

    llvm::StringRef symbol_name =
        strtab_data.PeekCStr(symbol.st_name).value_or("");
    uint64_t plt_index = plt_offset + i * plt_entsize;

    Symbol jump_symbol(
        i + start_id,          // Symbol table index
        symbol_name,           // symbol name.
        eSymbolTypeTrampoline, // Type of this symbol
        false,                 // Is this globally visible?
        false,                 // Is this symbol debug info?
        true,                  // Is this symbol a trampoline?
        true,                  // Is this symbol artificial?
        plt_section_sp, // Section in which this symbol is defined or null.
        plt_index,      // Offset in section or symbol value.
        plt_entsize,    // Size in bytes of this symbol.
        true,           // Size is valid
        false,          // Contains linker annotations?
        0);             // Symbol flags.

    symbol_table->AddSymbol(jump_symbol);
  }

  return i;
}

unsigned
ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
                                      const ELFSectionHeaderInfo *rel_hdr,
                                      user_id_t rel_id) {
  assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);

  // The link field points to the associated symbol table.
  user_id_t symtab_id = rel_hdr->sh_link;

  // If the link field doesn't point to the appropriate symbol name table then
  // try to find it by name as some compiler don't fill in the link fields.
  if (!symtab_id)
    symtab_id = GetSectionIndexByName(".dynsym");

  // Get PLT section.  We cannot use rel_hdr->sh_info, since current linkers
  // point that to the .got.plt or .got section instead of .plt.
  user_id_t plt_id = GetSectionIndexByName(".plt");

  if (!symtab_id || !plt_id)
    return 0;

  const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
  if (!plt_hdr)
    return 0;

  const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id);
  if (!sym_hdr)
    return 0;

  SectionList *section_list = m_sections_up.get();
  if (!section_list)
    return 0;

  Section *rel_section = section_list->FindSectionByID(rel_id).get();
  if (!rel_section)
    return 0;

  SectionSP plt_section_sp(section_list->FindSectionByID(plt_id));
  if (!plt_section_sp)
    return 0;

  Section *symtab = section_list->FindSectionByID(symtab_id).get();
  if (!symtab)
    return 0;

  // sh_link points to associated string table.
  Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link).get();
  if (!strtab)
    return 0;

  DataExtractor rel_data;
  if (!ReadSectionData(rel_section, rel_data))
    return 0;

  DataExtractor symtab_data;
  if (!ReadSectionData(symtab, symtab_data))
    return 0;

  DataExtractor strtab_data;
  if (!ReadSectionData(strtab, strtab_data))
    return 0;

  unsigned rel_type = PLTRelocationType();
  if (!rel_type)
    return 0;

  return ParsePLTRelocations(symbol_table, start_id, rel_type, &m_header,
                             rel_hdr, plt_hdr, sym_hdr, plt_section_sp,
                             rel_data, symtab_data, strtab_data);
}

/// Returns the \p size bytes at \p offset in \p debug_data for a relocation to
/// patch, or reports an error and returns null if they overrun the section.
static uint8_t *GetRelocationTarget(DataExtractor &debug_data,
                                    Section *rel_section, uint64_t offset,
                                    size_t size) {
  if (!debug_data.ValidOffsetForDataOfSize(offset, size)) {
    rel_section->GetModule()->ReportError("relocation outside of section {0}",
                                          rel_section->GetName());
    return nullptr;
  }
  DataBufferSP data_buffer_sp = debug_data.GetSharedDataBuffer();
  // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
  WritableDataBuffer *data_buffer =
      llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
  return data_buffer->GetBytes() + debug_data.GetSharedDataOffset() + offset;
}

static void ApplyELF64ABS64Relocation(Symtab *symtab, ELFRelocation &rel,
                                      DataExtractor &debug_data,
                                      Section *rel_section) {
  const Symbol *symbol =
      symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel));
  if (symbol) {
    addr_t value = symbol->GetAddressRef().GetFileAddress();
    uint8_t *dst = GetRelocationTarget(debug_data, rel_section,
                                       ELFRelocation::RelocOffset64(rel),
                                       sizeof(uint64_t));
    if (!dst)
      return;
    uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
    memcpy(dst, &val_offset, sizeof(uint64_t));
  }
}

static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel,
                                      DataExtractor &debug_data,
                                      Section *rel_section, bool is_signed) {
  const Symbol *symbol =
      symtab->FindSymbolByID(ELFRelocation::RelocSymbol64(rel));
  if (symbol) {
    addr_t value = symbol->GetAddressRef().GetFileAddress();
    value += ELFRelocation::RelocAddend32(rel);
    if ((!is_signed && (value > UINT32_MAX)) ||
        (is_signed &&
         ((int64_t)value > INT32_MAX || (int64_t)value < INT32_MIN))) {
      Log *log = GetLog(LLDBLog::Modules);
      LLDB_LOGF(log, "Failed to apply debug info relocations");
      return;
    }
    uint32_t truncated_addr = (value & 0xFFFFFFFF);
    uint8_t *dst = GetRelocationTarget(debug_data, rel_section,
                                       ELFRelocation::RelocOffset32(rel),
                                       sizeof(uint32_t));
    if (!dst)
      return;
    memcpy(dst, &truncated_addr, sizeof(uint32_t));
  }
}

static void ApplyELF32ABS32RelRelocation(Symtab *symtab, ELFRelocation &rel,
                                         DataExtractor &debug_data,
                                         Section *rel_section) {
  Log *log = GetLog(LLDBLog::Modules);
  const Symbol *symbol =
      symtab->FindSymbolByID(ELFRelocation::RelocSymbol32(rel));
  if (symbol) {
    addr_t value = symbol->GetAddressRef().GetFileAddress();
    if (value == LLDB_INVALID_ADDRESS) {
      const char *name = symbol->GetName().GetCString();
      LLDB_LOGF(log, "Debug info symbol invalid: %s", name);
      return;
    }
    assert(llvm::isUInt<32>(value) && "Valid addresses are 32-bit");
    uint8_t *dst = GetRelocationTarget(debug_data, rel_section,
                                       ELFRelocation::RelocOffset32(rel),
                                       sizeof(uint32_t));
    if (!dst)
      return;
    // Implicit addend is stored inline as a signed value.
    int32_t addend;
    memcpy(&addend, dst, sizeof(int32_t));
    // The sum must be positive. This extra check prevents UB from overflow in
    // the actual range check below.
    if (addend < 0 && static_cast<uint32_t>(-addend) > value) {
      LLDB_LOGF(log, "Debug info relocation overflow: 0x%" PRIx64,
                static_cast<int64_t>(value) + addend);
      return;
    }
    if (!llvm::isUInt<32>(value + addend)) {
      LLDB_LOGF(log, "Debug info relocation out of range: 0x%" PRIx64, value);
      return;
    }
    uint32_t addr = value + addend;
    memcpy(dst, &addr, sizeof(uint32_t));
  }
}

unsigned ObjectFileELF::ApplyRelocations(
    Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
    const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
    DataExtractor &rel_data, DataExtractor &symtab_data,
    DataExtractor &debug_data, Section *rel_section) {
  ELFRelocation rel(rel_hdr->sh_type);
  lldb::addr_t offset = 0;
  const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
  typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
  reloc_info_fn reloc_type;
  reloc_info_fn reloc_symbol;

  if (hdr->Is32Bit()) {
    reloc_type = ELFRelocation::RelocType32;
    reloc_symbol = ELFRelocation::RelocSymbol32;
  } else {
    reloc_type = ELFRelocation::RelocType64;
    reloc_symbol = ELFRelocation::RelocSymbol64;
  }

  for (unsigned i = 0; i < num_relocations; ++i) {
    if (!rel.Parse(rel_data, &offset)) {
      GetModule()->ReportError(".rel{0}[{1:d}] failed to parse relocation",
                               rel_section->GetName(), i);
      break;
    }
    const Symbol *symbol = nullptr;

    if (hdr->Is32Bit()) {
      switch (hdr->e_machine) {
      case llvm::ELF::EM_ARM:
        switch (reloc_type(rel)) {
        case R_ARM_ABS32:
          ApplyELF32ABS32RelRelocation(symtab, rel, debug_data, rel_section);
          break;
        case R_ARM_REL32:
          GetModule()->ReportError("unsupported AArch32 relocation:"
                                   " .rel{0}[{1}], type {2}",
                                   rel_section->GetName(), i, reloc_type(rel));
          break;
        default:
          assert(false && "unexpected relocation type");
        }
        break;
      case llvm::ELF::EM_386:
        switch (reloc_type(rel)) {
        case R_386_32:
          symbol = symtab->FindSymbolByID(reloc_symbol(rel));
          if (symbol) {
            uint32_t *dst = reinterpret_cast<uint32_t *>(GetRelocationTarget(
                debug_data, rel_section, ELFRelocation::RelocOffset32(rel),
                sizeof(uint32_t)));
            if (!dst)
              break;

            addr_t value = symbol->GetAddressRef().GetFileAddress();
            if (rel.IsRela()) {
              value += ELFRelocation::RelocAddend32(rel);
            } else {
              value += *dst;
            }
            *dst = value;
          } else {
            GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
                                     rel_section->GetName(), i,
                                     reloc_symbol(rel));
          }
          break;
        case R_386_NONE:
        case R_386_PC32:
          GetModule()->ReportError("unsupported i386 relocation:"
                                   " .rel{0}[{1}], type {2}",
                                   rel_section->GetName(), i, reloc_type(rel));
          break;
        default:
          assert(false && "unexpected relocation type");
          break;
        }
        break;
      default:
        GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}", hdr->e_machine);
        break;
      }
    } else {
      switch (hdr->e_machine) {
      case llvm::ELF::EM_AARCH64:
        switch (reloc_type(rel)) {
        case R_AARCH64_ABS64:
          ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
          break;
        case R_AARCH64_ABS32:
          ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
          break;
        default:
          assert(false && "unexpected relocation type");
        }
        break;
      case llvm::ELF::EM_LOONGARCH:
        switch (reloc_type(rel)) {
        case R_LARCH_64:
          ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
          break;
        case R_LARCH_32:
          ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
          break;
        default:
          assert(false && "unexpected relocation type");
        }
        break;
      case llvm::ELF::EM_X86_64:
        switch (reloc_type(rel)) {
        case R_X86_64_64:
          ApplyELF64ABS64Relocation(symtab, rel, debug_data, rel_section);
          break;
        case R_X86_64_32:
          ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section,
                                    false);
          break;
        case R_X86_64_32S:
          ApplyELF64ABS32Relocation(symtab, rel, debug_data, rel_section, true);
          break;
        case R_X86_64_PC32:
        default:
          assert(false && "unexpected relocation type");
        }
        break;
      default:
        GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}", hdr->e_machine);
        break;
      }
    }
  }

  return 0;
}

unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
                                              user_id_t rel_id,
                                              lldb_private::Symtab *thetab) {
  assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);

  // Parse in the section list if needed.
  SectionList *section_list = GetSectionList();
  if (!section_list)
    return 0;

  user_id_t symtab_id = rel_hdr->sh_link;
  user_id_t debug_id = rel_hdr->sh_info;

  const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
  if (!symtab_hdr)
    return 0;

  const ELFSectionHeader *debug_hdr = GetSectionHeaderByIndex(debug_id);
  if (!debug_hdr)
    return 0;

  Section *rel = section_list->FindSectionByID(rel_id).get();
  if (!rel)
    return 0;

  Section *symtab = section_list->FindSectionByID(symtab_id).get();
  if (!symtab)
    return 0;

  Section *debug = section_list->FindSectionByID(debug_id).get();
  if (!debug)
    return 0;

  DataExtractorSP rel_data_sp = std::make_shared<DataExtractor>();
  DataExtractorSP symtab_data_sp = std::make_shared<DataExtractor>();
  DataExtractorSP debug_data_sp = std::make_shared<DataExtractor>();

  if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data_sp) &&
      GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data_sp) &&
      GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data_sp)) {
    ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr,
                     *rel_data_sp, *symtab_data_sp, *debug_data_sp, debug);
  }

  return 0;
}

void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
  ModuleSP module_sp(GetModule());
  if (!module_sp)
    return;

  Progress progress("Parsing symbol table",
                    m_file.GetFilename().nonEmptyOr("<Unknown>").str());
  ElapsedTime elapsed(module_sp->GetSymtabParseTime());

  // We always want to use the main object file so we (hopefully) only have one
  // cached copy of our symtab, dynamic sections, etc.
  ObjectFile *module_obj_file = module_sp->GetObjectFile();
  if (module_obj_file && module_obj_file != this)
    return module_obj_file->ParseSymtab(lldb_symtab);

  SectionList *section_list = module_sp->GetSectionList();
  if (!section_list)
    return;

  uint64_t symbol_id = 0;

  // Sharable objects and dynamic executables usually have 2 distinct symbol
  // tables, one named ".symtab", and the other ".dynsym". The dynsym is a
  // smaller version of the symtab that only contains global symbols. The
  // information found in the dynsym is therefore also found in the symtab,
  // while the reverse is not necessarily true.
  Section *symtab =
      section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
  if (symtab) {
    auto [num_symbols, address_class_map] =
        ParseSymbolTable(&lldb_symtab, symbol_id, symtab);
    m_address_class_map.merge(address_class_map);
    symbol_id += num_symbols;
  }

  // The symtab section is non-allocable and can be stripped, while the
  // .dynsym section which should always be always be there. To support the
  // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo
  // section, nomatter if .symtab was already parsed or not. This is because
  // minidebuginfo normally removes the .symtab symbols which have their
  // matching .dynsym counterparts.
  if (!symtab || GetSectionList()->FindSectionByName(".gnu_debugdata")) {
    Section *dynsym =
        section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
            .get();
    if (dynsym) {
      auto [num_symbols, address_class_map] =
          ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
      symbol_id += num_symbols;
      m_address_class_map.merge(address_class_map);
    } else {
      // Try and read the dynamic symbol table from the .dynamic section.
      uint32_t dynamic_num_symbols = 0;
      std::optional<DataExtractor> symtab_data =
          GetDynsymDataFromDynamic(dynamic_num_symbols);
      std::optional<DataExtractor> strtab_data = GetDynstrData();
      if (symtab_data && strtab_data) {
        auto [num_symbols_parsed, address_class_map] = ParseSymbols(
            &lldb_symtab, symbol_id, section_list, dynamic_num_symbols,
            symtab_data.value(), strtab_data.value());
        symbol_id += num_symbols_parsed;
        m_address_class_map.merge(address_class_map);
      }
    }
  }

  // DT_JMPREL
  //      If present, this entry's d_ptr member holds the address of
  //      relocation
  //      entries associated solely with the procedure linkage table.
  //      Separating
  //      these relocation entries lets the dynamic linker ignore them during
  //      process initialization, if lazy binding is enabled. If this entry is
  //      present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
  //      also be present.
  const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
  if (symbol) {
    // Synthesize trampoline symbols to help navigate the PLT.
    addr_t addr = symbol->d_ptr;
    Section *reloc_section =
        section_list->FindSectionContainingFileAddress(addr).get();
    if (reloc_section) {
      user_id_t reloc_id = reloc_section->GetID();
      const ELFSectionHeaderInfo *reloc_header =
          GetSectionHeaderByIndex(reloc_id);
      if (reloc_header)
        ParseTrampolineSymbols(&lldb_symtab, symbol_id, reloc_header, reloc_id);
    }
  }

  if (DWARFCallFrameInfo *eh_frame =
          GetModule()->GetUnwindTable().GetEHFrameInfo()) {
    ParseUnwindSymbols(&lldb_symtab, eh_frame);
  }

  // In the event that there's no symbol entry for the entry point we'll
  // artificially create one. We delegate to the symtab object the figuring
  // out of the proper size, this will usually make it span til the next
  // symbol it finds in the section. This means that if there are missing
  // symbols the entry point might span beyond its function definition.
  // We're fine with this as it doesn't make it worse than not having a
  // symbol entry at all.
  if (CalculateType() == eTypeExecutable) {
    ArchSpec arch = GetArchitecture();
    auto entry_point_addr = GetEntryPointAddress();
    bool is_valid_entry_point =
        entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset();
    addr_t entry_point_file_addr = entry_point_addr.GetFileAddress();
    if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress(
                                    entry_point_file_addr)) {
      uint64_t symbol_id = lldb_symtab.GetNumSymbols();
      // Don't set the name for any synthetic symbols, the Symbol
      // object will generate one if needed when the name is accessed
      // via accessors.
      SectionSP section_sp = entry_point_addr.GetSection();
      Symbol symbol(
          /*symID=*/symbol_id,
          /*name=*/llvm::StringRef(), // Name will be auto generated.
          /*type=*/eSymbolTypeCode,
          /*external=*/true,
          /*is_debug=*/false,
          /*is_trampoline=*/false,
          /*is_artificial=*/true,
          /*section_sp=*/section_sp,
          /*offset=*/entry_point_addr.GetOffset(),
          /*size=*/0, // FDE can span multiple symbols so don't use its size.
          /*size_is_valid=*/false,
          /*contains_linker_annotations=*/false,
          /*flags=*/0);
      // When the entry point is arm thumb we need to explicitly set its
      // class address to reflect that. This is important because expression
      // evaluation relies on correctly setting a breakpoint at this
      // address.
      if (arch.GetMachine() == llvm::Triple::arm &&
          (entry_point_file_addr & 1)) {
        symbol.GetAddressRef().Slide(-1);
        m_address_class_map[entry_point_file_addr - 1] =
            AddressClass::eCodeAlternateISA;
      } else {
        m_address_class_map[entry_point_file_addr] = AddressClass::eCode;
      }
      lldb_symtab.AddSymbol(symbol);
    }
  }
}

void ObjectFileELF::RelocateSection(lldb_private::Section *section)
{
  static llvm::StringRef debug_prefix(".debug");

  // Set relocated bit so we stop getting called, regardless of whether we
  // actually relocate.
  section->SetIsRelocated(true);

  // We only relocate in ELF relocatable files
  if (CalculateType() != eTypeObjectFile)
    return;

  llvm::StringRef section_name = section->GetName();
  // Can't relocate that which can't be named
  if (section_name.empty())
    return;

  // We don't relocate non-debug sections at the moment
  if (!section_name.starts_with(debug_prefix))
    return;

  // Relocation section names to look for
  std::string needle = std::string(".rel") + section_name.str();
  std::string needlea = std::string(".rela") + section_name.str();

  for (SectionHeaderCollIter I = m_section_headers.begin();
       I != m_section_headers.end(); ++I) {
    if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) {
      llvm::StringRef hay_name(I->section_name);
      if (hay_name.empty())
        continue;
      if (needle == hay_name || needlea == hay_name) {
        const ELFSectionHeader &reloc_header = *I;
        user_id_t reloc_id = SectionIndex(I);
        RelocateDebugSections(&reloc_header, reloc_id, GetSymtab());
        break;
      }
    }
  }
}

void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
                                       DWARFCallFrameInfo *eh_frame) {
  SectionList *section_list = GetSectionList();
  if (!section_list)
    return;

  // First we save the new symbols into a separate list and add them to the
  // symbol table after we collected all symbols we want to add. This is
  // neccessary because adding a new symbol invalidates the internal index of
  // the symtab what causing the next lookup to be slow because it have to
  // recalculate the index first.
  std::vector<Symbol> new_symbols;

  size_t num_symbols = symbol_table->GetNumSymbols();
  uint64_t last_symbol_id =
      num_symbols ? symbol_table->SymbolAtIndex(num_symbols - 1)->GetID() : 0;
  eh_frame->ForEachFDEEntries([&](lldb::addr_t file_addr, uint32_t size,
                                  dw_offset_t) {
    Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
    if (symbol) {
      if (!symbol->GetByteSizeIsValid()) {
        symbol->SetByteSize(size);
        symbol->SetSizeIsSynthesized(true);
      }
    } else {
      SectionSP section_sp =
          section_list->FindSectionContainingFileAddress(file_addr);
      if (section_sp) {
        addr_t offset = file_addr - section_sp->GetFileAddress();
        uint64_t symbol_id = ++last_symbol_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.
        Symbol eh_symbol(
            /*symID=*/symbol_id,
            /*name=*/llvm::StringRef(), // Name will be auto generated.
            /*type=*/eSymbolTypeCode,
            /*external=*/true,
            /*is_debug=*/false,
            /*is_trampoline=*/false,
            /*is_artificial=*/true,
            /*section_sp=*/section_sp,
            /*offset=*/offset,
            /*size=*/0, // FDE can span multiple symbols so don't use its size.
            /*size_is_valid=*/false,
            /*contains_linker_annotations=*/false,
            /*flags=*/0);
        new_symbols.push_back(eh_symbol);
      }
    }
    return true;
  });

  for (const Symbol &s : new_symbols)
    symbol_table->AddSymbol(s);
}

bool ObjectFileELF::IsStripped() {
  // TODO: determine this for ELF
  return false;
}

//===----------------------------------------------------------------------===//
// Dump
//
// Dump the specifics of the runtime file container (such as any headers
// segments, sections, etc).
void ObjectFileELF::Dump(Stream *s) {
  ModuleSP module_sp(GetModule());
  if (!module_sp) {
    return;
  }

  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
  s->Printf("%p: ", static_cast<void *>(this));
  s->Indent();
  s->PutCString("ObjectFileELF");

  ArchSpec header_arch = GetArchitecture();

  *s << ", file = '" << m_file
     << "', arch = " << header_arch.GetArchitectureName();
  if (m_memory_addr != LLDB_INVALID_ADDRESS)
    s->Printf(", addr = %#16.16" PRIx64, m_memory_addr);
  s->EOL();

  DumpELFHeader(s, m_header);
  s->EOL();
  DumpELFProgramHeaders(s);
  s->EOL();
  DumpELFSectionHeaders(s);
  s->EOL();
  SectionList *section_list = GetSectionList();
  if (section_list)
    section_list->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
                       UINT32_MAX);
  Symtab *symtab = GetSymtab();
  if (symtab)
    symtab->Dump(s, nullptr, eSortOrderNone);
  s->EOL();
  DumpDependentModules(s);
  s->EOL();
  DumpELFDynamic(s);
  s->EOL();
  Address image_info_addr = GetImageInfoAddress(nullptr);
  if (image_info_addr.IsValid())
    s->Printf("image_info_address = %#16.16" PRIx64 "\n",
              image_info_addr.GetFileAddress());
}

// DumpELFHeader
//
// Dump the ELF header to the specified output stream
void ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header) {
  s->PutCString("ELF Header\n");
  s->Printf("e_ident[EI_MAG0   ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
  s->Printf("e_ident[EI_MAG1   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG1],
            header.e_ident[EI_MAG1]);
  s->Printf("e_ident[EI_MAG2   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG2],
            header.e_ident[EI_MAG2]);
  s->Printf("e_ident[EI_MAG3   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG3],
            header.e_ident[EI_MAG3]);

  s->Printf("e_ident[EI_CLASS  ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
  s->Printf("e_ident[EI_DATA   ] = 0x%2.2x ", header.e_ident[EI_DATA]);
  DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
  s->Printf("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
  s->Printf("e_ident[EI_PAD    ] = 0x%2.2x\n", header.e_ident[EI_PAD]);

  s->Printf("e_type      = 0x%4.4x ", header.e_type);
  DumpELFHeader_e_type(s, header.e_type);
  s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
  s->Printf("e_version   = 0x%8.8x\n", header.e_version);
  s->Printf("e_entry     = 0x%8.8" PRIx64 "\n", header.e_entry);
  s->Printf("e_phoff     = 0x%8.8" PRIx64 "\n", header.e_phoff);
  s->Printf("e_shoff     = 0x%8.8" PRIx64 "\n", header.e_shoff);
  s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
  s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
  s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
  s->Printf("e_phnum     = 0x%8.8x\n", header.e_phnum);
  s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
  s->Printf("e_shnum     = 0x%8.8x\n", header.e_shnum);
  s->Printf("e_shstrndx  = 0x%8.8x\n", header.e_shstrndx);
}

// DumpELFHeader_e_type
//
// Dump an token value for the ELF header member e_type
void ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type) {
  switch (e_type) {
  case ET_NONE:
    *s << "ET_NONE";
    break;
  case ET_REL:
    *s << "ET_REL";
    break;
  case ET_EXEC:
    *s << "ET_EXEC";
    break;
  case ET_DYN:
    *s << "ET_DYN";
    break;
  case ET_CORE:
    *s << "ET_CORE";
    break;
  default:
    break;
  }
}

// DumpELFHeader_e_ident_EI_DATA
//
// Dump an token value for the ELF header member e_ident[EI_DATA]
void ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s,
                                                  unsigned char ei_data) {
  switch (ei_data) {
  case ELFDATANONE:
    *s << "ELFDATANONE";
    break;
  case ELFDATA2LSB:
    *s << "ELFDATA2LSB - Little Endian";
    break;
  case ELFDATA2MSB:
    *s << "ELFDATA2MSB - Big Endian";
    break;
  default:
    break;
  }
}

// DumpELFProgramHeader
//
// Dump a single ELF program header to the specified output stream
void ObjectFileELF::DumpELFProgramHeader(Stream *s,
                                         const ELFProgramHeader &ph) {
  DumpELFProgramHeader_p_type(s, ph.p_type);
  s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset,
            ph.p_vaddr, ph.p_paddr);
  s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz,
            ph.p_flags);

  DumpELFProgramHeader_p_flags(s, ph.p_flags);
  s->Printf(") %8.8" PRIx64, ph.p_align);
}

// DumpELFProgramHeader_p_type
//
// Dump an token value for the ELF program header member p_type which describes
// the type of the program header
void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
  const int kStrWidth = 15;
  switch (p_type) {
    CASE_AND_STREAM(s, PT_NULL, kStrWidth);
    CASE_AND_STREAM(s, PT_LOAD, kStrWidth);
    CASE_AND_STREAM(s, PT_DYNAMIC, kStrWidth);
    CASE_AND_STREAM(s, PT_INTERP, kStrWidth);
    CASE_AND_STREAM(s, PT_NOTE, kStrWidth);
    CASE_AND_STREAM(s, PT_SHLIB, kStrWidth);
    CASE_AND_STREAM(s, PT_PHDR, kStrWidth);
    CASE_AND_STREAM(s, PT_TLS, kStrWidth);
    CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
  default:
    s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
    break;
  }
}

// DumpELFProgramHeader_p_flags
//
// Dump an token value for the ELF program header member p_flags
void ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags) {
  *s << ((p_flags & PF_X) ? "PF_X" : "    ")
     << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
     << ((p_flags & PF_W) ? "PF_W" : "    ")
     << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
     << ((p_flags & PF_R) ? "PF_R" : "    ");
}

// DumpELFProgramHeaders
//
// Dump all of the ELF program header to the specified output stream
void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
  if (!ParseProgramHeaders())
    return;

  s->PutCString("Program Headers\n");
  s->PutCString("IDX  p_type          p_offset p_vaddr  p_paddr  "
                "p_filesz p_memsz  p_flags                   p_align\n");
  s->PutCString("==== --------------- -------- -------- -------- "
                "-------- -------- ------------------------- --------\n");

  for (const auto &H : llvm::enumerate(m_program_headers)) {
    s->Format("[{0,2}] ", H.index());
    ObjectFileELF::DumpELFProgramHeader(s, H.value());
    s->EOL();
  }
}

// DumpELFSectionHeader
//
// Dump a single ELF section header to the specified output stream
void ObjectFileELF::DumpELFSectionHeader(Stream *s,
                                         const ELFSectionHeaderInfo &sh) {
  s->Printf("%8.8x ", sh.sh_name);
  DumpELFSectionHeader_sh_type(s, sh.sh_type);
  s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
  DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
  s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr,
            sh.sh_offset, sh.sh_size);
  s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
  s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
}

// DumpELFSectionHeader_sh_type
//
// Dump an token value for the ELF section header member sh_type which
// describes the type of the section
void ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type) {
  const int kStrWidth = 12;
  switch (sh_type) {
    CASE_AND_STREAM(s, SHT_NULL, kStrWidth);
    CASE_AND_STREAM(s, SHT_PROGBITS, kStrWidth);
    CASE_AND_STREAM(s, SHT_SYMTAB, kStrWidth);
    CASE_AND_STREAM(s, SHT_STRTAB, kStrWidth);
    CASE_AND_STREAM(s, SHT_RELA, kStrWidth);
    CASE_AND_STREAM(s, SHT_HASH, kStrWidth);
    CASE_AND_STREAM(s, SHT_DYNAMIC, kStrWidth);
    CASE_AND_STREAM(s, SHT_NOTE, kStrWidth);
    CASE_AND_STREAM(s, SHT_NOBITS, kStrWidth);
    CASE_AND_STREAM(s, SHT_REL, kStrWidth);
    CASE_AND_STREAM(s, SHT_SHLIB, kStrWidth);
    CASE_AND_STREAM(s, SHT_DYNSYM, kStrWidth);
    CASE_AND_STREAM(s, SHT_LOPROC, kStrWidth);
    CASE_AND_STREAM(s, SHT_HIPROC, kStrWidth);
    CASE_AND_STREAM(s, SHT_LOUSER, kStrWidth);
    CASE_AND_STREAM(s, SHT_HIUSER, kStrWidth);
  default:
    s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
    break;
  }
}

// DumpELFSectionHeader_sh_flags
//
// Dump an token value for the ELF section header member sh_flags
void ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s,
                                                  elf_xword sh_flags) {
  *s << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
     << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
     << ((sh_flags & SHF_ALLOC) ? "ALLOC" : "     ")
     << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
     << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : "         ");
}

// DumpELFSectionHeaders
//
// Dump all of the ELF section header to the specified output stream
void ObjectFileELF::DumpELFSectionHeaders(Stream *s) {
  if (!ParseSectionHeaders())
    return;

  s->PutCString("Section Headers\n");
  s->PutCString("IDX  name     type         flags                            "
                "addr     offset   size     link     info     addralgn "
                "entsize  Name\n");
  s->PutCString("==== -------- ------------ -------------------------------- "
                "-------- -------- -------- -------- -------- -------- "
                "-------- ====================\n");

  uint32_t idx = 0;
  for (SectionHeaderCollConstIter I = m_section_headers.begin();
       I != m_section_headers.end(); ++I, ++idx) {
    s->Printf("[%2u] ", idx);
    ObjectFileELF::DumpELFSectionHeader(s, *I);
    const std::string &section_name = I->section_name;
    if (!section_name.empty())
      *s << ' ' << section_name << "\n";
  }
}

void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
  size_t num_modules = ParseDependentModules();

  if (num_modules > 0) {
    s->PutCString("Dependent Modules:\n");
    for (unsigned i = 0; i < num_modules; ++i) {
      const FileSpec &spec = m_filespec_up->GetFileSpecAtIndex(i);
      s->Format("   {0}\n", spec.GetFilename());
    }
  }
}

std::string static getDynamicTagAsString(uint16_t Arch, uint64_t Type) {
#define DYNAMIC_STRINGIFY_ENUM(tag, value)                                     \
  case value:                                                                  \
    return #tag;

#define DYNAMIC_TAG(n, v)
  switch (Arch) {
  case llvm::ELF::EM_AARCH64:
    switch (Type) {
#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef AARCH64_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_HEXAGON:
    switch (Type) {
#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef HEXAGON_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_MIPS:
    switch (Type) {
#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef MIPS_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_PPC:
    switch (Type) {
#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef PPC_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_PPC64:
    switch (Type) {
#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef PPC64_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_RISCV:
    switch (Type) {
#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef RISCV_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_SPARC:
  case llvm::ELF::EM_SPARC32PLUS:
  case llvm::ELF::EM_SPARCV9:
    switch (Type) {
#define SPARC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef SPARC_DYNAMIC_TAG
    }
    break;

  case llvm::ELF::EM_X86_64:
    switch (Type) {
#define X86_64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
#include "llvm/BinaryFormat/DynamicTags.def"
#undef X86_64_DYNAMIC_TAG
    }
    break;
  }
#undef DYNAMIC_TAG
  switch (Type) {
// Now handle all dynamic tags except the architecture specific ones
#define AARCH64_DYNAMIC_TAG(name, value)
#define MIPS_DYNAMIC_TAG(name, value)
#define HEXAGON_DYNAMIC_TAG(name, value)
#define PPC_DYNAMIC_TAG(name, value)
#define PPC64_DYNAMIC_TAG(name, value)
#define RISCV_DYNAMIC_TAG(name, value)
#define SPARC_DYNAMIC_TAG(name, value)
#define X86_64_DYNAMIC_TAG(name, value)
// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
#define DYNAMIC_TAG_MARKER(name, value)
#define DYNAMIC_TAG(name, value)                                               \
  case value:                                                                  \
    return #name;
#include "llvm/BinaryFormat/DynamicTags.def"
#undef DYNAMIC_TAG
#undef AARCH64_DYNAMIC_TAG
#undef MIPS_DYNAMIC_TAG
#undef HEXAGON_DYNAMIC_TAG
#undef PPC_DYNAMIC_TAG
#undef PPC64_DYNAMIC_TAG
#undef RISCV_DYNAMIC_TAG
#undef SPARC_DYNAMIC_TAG
#undef X86_64_DYNAMIC_TAG
#undef DYNAMIC_TAG_MARKER
#undef DYNAMIC_STRINGIFY_ENUM
  default:
    return "<unknown:>0x" + llvm::utohexstr(Type, true);
  }
}

void ObjectFileELF::DumpELFDynamic(lldb_private::Stream *s) {
  ParseDynamicSymbols();
  if (m_dynamic_symbols.empty())
    return;

  s->PutCString(".dynamic:\n");
  s->PutCString("IDX  d_tag            d_val/d_ptr\n");
  s->PutCString("==== ---------------- ------------------\n");
  uint32_t idx = 0;
  for (const auto &entry : m_dynamic_symbols) {
    s->Printf("[%2u] ", idx++);
    s->Printf(
        "%-16s 0x%16.16" PRIx64,
        getDynamicTagAsString(m_header.e_machine, entry.symbol.d_tag).c_str(),
        entry.symbol.d_ptr);
    if (!entry.name.empty())
      s->Printf(" \"%s\"", entry.name.c_str());
    s->EOL();
  }
}

ArchSpec ObjectFileELF::GetArchitecture() {
  if (!ParseHeader())
    return ArchSpec();

  if (m_section_headers.empty()) {
    // Allow elf notes to be parsed which may affect the detected architecture.
    ParseSectionHeaders();
  }

  if (CalculateType() == eTypeCoreFile &&
      !m_arch_spec.TripleOSWasSpecified()) {
    // Core files don't have section headers yet they have PT_NOTE program
    // headers that might shed more light on the architecture
    for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
      if (H.p_type != PT_NOTE || H.p_offset == 0 || H.p_filesz == 0)
        continue;
      DataExtractor data;
      if (data.SetData(*m_data_nsp, H.p_offset, H.p_filesz) == H.p_filesz) {
        UUID uuid;
        RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
      }
    }
  }
  return m_arch_spec;
}

ObjectFile::Type ObjectFileELF::CalculateType() {
  switch (m_header.e_type) {
  case llvm::ELF::ET_NONE:
    // 0 - No file type
    return eTypeUnknown;

  case llvm::ELF::ET_REL:
    // 1 - Relocatable file
    return eTypeObjectFile;

  case llvm::ELF::ET_EXEC:
    // 2 - Executable file
    return eTypeExecutable;

  case llvm::ELF::ET_DYN:
    // 3 - Shared object file
    return eTypeSharedLibrary;

  case ET_CORE:
    // 4 - Core file
    return eTypeCoreFile;

  default:
    break;
  }
  return eTypeUnknown;
}

ObjectFile::Strata ObjectFileELF::CalculateStrata() {
  switch (m_header.e_type) {
  case llvm::ELF::ET_NONE:
    // 0 - No file type
    return eStrataUnknown;

  case llvm::ELF::ET_REL:
    // 1 - Relocatable file
    return eStrataUnknown;

  case llvm::ELF::ET_EXEC:
    // 2 - Executable file
    {
      SectionList *section_list = GetSectionList();
      if (section_list) {
        llvm::StringRef loader_section_name(".interp");
        SectionSP loader_section =
            section_list->FindSectionByName(loader_section_name);
        if (loader_section) {
          char buffer[256];
          size_t read_size =
              ReadSectionData(loader_section.get(), 0, buffer, sizeof(buffer));

          // We compare the content of .interp section
          // It will contains \0 when counting read_size, so the size needs to
          // decrease by one
          llvm::StringRef loader_name(buffer, read_size - 1);
          llvm::StringRef freebsd_kernel_loader_name("/red/herring");
          if (loader_name == freebsd_kernel_loader_name)
            return eStrataKernel;
        }
      }
      return eStrataUser;
    }

  case llvm::ELF::ET_DYN:
    // 3 - Shared object file
    // TODO: is there any way to detect that an shared library is a kernel
    // related executable by inspecting the program headers, section headers,
    // symbols, or any other flag bits???
    return eStrataUnknown;

  case ET_CORE:
    // 4 - Core file
    // TODO: is there any way to detect that an core file is a kernel
    // related executable by inspecting the program headers, section headers,
    // symbols, or any other flag bits???
    return eStrataUnknown;

  default:
    break;
  }
  return eStrataUnknown;
}

size_t ObjectFileELF::ReadSectionData(Section *section,
                       lldb::offset_t section_offset, void *dst,
                       size_t dst_len) {
  // If some other objectfile owns this data, pass this to them.
  if (section->GetObjectFile() != this)
    return section->GetObjectFile()->ReadSectionData(section, section_offset,
                                                     dst, dst_len);

  if (!section->Test(SHF_COMPRESSED))
    return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len);

  // For compressed sections we need to read to full data to be able to
  // decompress.
  DataExtractor data;
  ReadSectionData(section, data);
  return data.CopyData(section_offset, dst_len, dst);
}

size_t ObjectFileELF::ReadSectionData(Section *section,
                                      DataExtractor &section_data) {
  // If some other objectfile owns this data, pass this to them.
  if (section->GetObjectFile() != this)
    return section->GetObjectFile()->ReadSectionData(section, section_data);

  size_t result = ObjectFile::ReadSectionData(section, section_data);
  if (result == 0 || !(section->Get() & llvm::ELF::SHF_COMPRESSED))
    return result;

  auto Decompressor = llvm::object::Decompressor::create(
      section->GetName(),
      {reinterpret_cast<const char *>(section_data.GetDataStart()),
       size_t(section_data.GetByteSize())},
      GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
  if (!Decompressor) {
    GetModule()->ReportWarning(
        "unable to initialize decompressor for section '{0}': {1}",
        section->GetName(), llvm::toString(Decompressor.takeError()).c_str());
    section_data.Clear();
    return 0;
  }

  auto buffer_sp =
      std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0);
  if (auto error = Decompressor->decompress(
          {buffer_sp->GetBytes(), size_t(buffer_sp->GetByteSize())})) {
    GetModule()->ReportWarning("decompression of section '{0}' failed: {1}",
                               section->GetName(),
                               llvm::toString(std::move(error)).c_str());
    section_data.Clear();
    return 0;
  }

  section_data.SetData(buffer_sp);
  return buffer_sp->GetByteSize();
}

llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
  ParseProgramHeaders();
  return m_program_headers;
}

DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) {
  // Try and read the program header from our cached m_data_nsp which can come
  // from the file on disk being mmap'ed or from the initial part of the ELF
  // file we read from memory and cached.
  DataExtractor data = DataExtractor(*m_data_nsp, H.p_offset, H.p_filesz);
  if (data.GetByteSize() == H.p_filesz)
    return data;
  if (IsInMemory()) {
    // We have a ELF file in process memory, read the program header data from
    // the process.
    if (ProcessSP process_sp = m_process_wp.lock()) {
      const lldb::offset_t base_file_addr = GetBaseAddress().GetFileAddress();
      const addr_t load_bias = m_memory_addr - base_file_addr;
      const addr_t data_addr = H.p_vaddr + load_bias;
      if (DataBufferSP data_sp = ReadMemory(process_sp, data_addr, H.p_memsz))
        return DataExtractor(data_sp, GetByteOrder(), GetAddressByteSize());
    }
  }
  return DataExtractor();
}

bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
  for (const ELFProgramHeader &H : ProgramHeaders()) {
    if (H.p_paddr != 0)
      return true;
  }
  return false;
}

std::vector<ObjectFile::LoadableData>
ObjectFileELF::GetLoadableData(Target &target) {
  // Create a list of loadable data from loadable segments, using physical
  // addresses if they aren't all null
  std::vector<LoadableData> loadables;
  bool should_use_paddr = AnySegmentHasPhysicalAddress();
  for (const ELFProgramHeader &H : ProgramHeaders()) {
    LoadableData loadable;
    if (H.p_type != llvm::ELF::PT_LOAD)
      continue;
    loadable.Dest = should_use_paddr ? H.p_paddr : H.p_vaddr;
    if (loadable.Dest == LLDB_INVALID_ADDRESS)
      continue;
    if (H.p_filesz == 0)
      continue;
    auto segment_data = GetSegmentData(H);
    loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
                                                segment_data.GetByteSize());
    loadables.push_back(loadable);
  }
  return loadables;
}

lldb::WritableDataBufferSP
ObjectFileELF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
                                   uint64_t Offset) {
  return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
                                                         Offset);
}

std::optional<DataExtractor>
ObjectFileELF::ReadDataFromDynamic(const ELFDynamic *dyn, uint64_t length,
                                   uint64_t offset) {
  // ELFDynamic values contain a "d_ptr" member that will be a load address if
  // we have an ELF file read from memory, or it will be a file address if it
  // was read from a ELF file. This function will correctly fetch data pointed
  // to by the ELFDynamic::d_ptr, or return std::nullopt if the data isn't
  // available.
  const lldb::addr_t d_ptr_addr = dyn->d_ptr + offset;
  if (ProcessSP process_sp = m_process_wp.lock()) {
    if (DataBufferSP data_sp = ReadMemory(process_sp, d_ptr_addr, length))
      return DataExtractor(data_sp, GetByteOrder(), GetAddressByteSize());
  } else {
    // We have an ELF file with no section headers or we didn't find the
    // .dynamic section. Try and find the .dynstr section.
    Address addr;
    if (!addr.ResolveAddressUsingFileSections(d_ptr_addr, GetSectionList()))
      return std::nullopt;
    DataExtractor data;
    addr.GetSection()->GetSectionData(data);
    return DataExtractor(data, d_ptr_addr - addr.GetSection()->GetFileAddress(),
                         length);
  }
  return std::nullopt;
}

std::optional<DataExtractor> ObjectFileELF::GetDynstrData() {
  if (SectionList *section_list = GetSectionList()) {
    // Find the SHT_DYNAMIC section.
    if (Section *dynamic =
            section_list
                ->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)
                .get()) {
      assert(dynamic->GetObjectFile() == this);
      if (const ELFSectionHeaderInfo *header =
              GetSectionHeaderByIndex(dynamic->GetID())) {
        // sh_link: section header index of string table used by entries in
        // the section.
        if (Section *dynstr =
                section_list->FindSectionByID(header->sh_link).get()) {
          DataExtractor data;
          if (ReadSectionData(dynstr, data))
            return data;
        }
      }
    }
  }

  // Every ELF file which represents an executable or shared library has
  // mandatory .dynamic entries. Two of these values are DT_STRTAB and DT_STRSZ
  // and represent the dynamic symbol tables's string table. These are needed
  // by the dynamic loader and we can read them from a process' address space.
  //
  // When loading and ELF file from memory, only the program headers are
  // guaranteed end up being mapped into memory, and we can find these values in
  // the PT_DYNAMIC segment.
  const ELFDynamic *strtab = FindDynamicSymbol(DT_STRTAB);
  const ELFDynamic *strsz = FindDynamicSymbol(DT_STRSZ);
  if (strtab == nullptr || strsz == nullptr)
    return std::nullopt;

  return ReadDataFromDynamic(strtab, strsz->d_val, /*offset=*/0);
}

std::optional<lldb_private::DataExtractor> ObjectFileELF::GetDynamicData() {
  DataExtractor data;
  // The PT_DYNAMIC program header describes where the .dynamic section is and
  // doesn't require parsing section headers. The PT_DYNAMIC is required by
  // executables and shared libraries so it will always be available.
  for (const ELFProgramHeader &H : ProgramHeaders()) {
    if (H.p_type == llvm::ELF::PT_DYNAMIC) {
      data = GetSegmentData(H);
      if (data.GetByteSize() > 0) {
        m_dynamic_base_addr = H.p_vaddr;
        return data;
      }
    }
  }
  // Fall back to using section headers.
  if (SectionList *section_list = GetSectionList()) {
    // Find the SHT_DYNAMIC section.
    if (Section *dynamic =
            section_list
                ->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)
                .get()) {
      assert(dynamic->GetObjectFile() == this);
      if (ReadSectionData(dynamic, data)) {
        m_dynamic_base_addr = dynamic->GetFileAddress();
        return data;
      }
    }
  }
  return std::nullopt;
}

std::optional<uint32_t> ObjectFileELF::GetNumSymbolsFromDynamicHash() {
  const ELFDynamic *hash = FindDynamicSymbol(DT_HASH);
  if (hash == nullptr)
    return std::nullopt;

  // The DT_HASH header looks like this:
  struct DtHashHeader {
    uint32_t nbucket;
    uint32_t nchain;
  };
  if (auto data = ReadDataFromDynamic(hash, 8)) {
    // We don't need the number of buckets value "nbucket", we just need the
    // "nchain" value which contains the number of symbols.
    offset_t offset = offsetof(DtHashHeader, nchain);
    return data->GetU32(&offset);
  }

  return std::nullopt;
}

std::optional<uint32_t> ObjectFileELF::GetNumSymbolsFromDynamicGnuHash() {
  const ELFDynamic *gnu_hash = FindDynamicSymbol(DT_GNU_HASH);
  if (gnu_hash == nullptr)
    return std::nullopt;

  // Create a DT_GNU_HASH header
  // https://flapenguin.me/elf-dt-gnu-hash
  struct DtGnuHashHeader {
    uint32_t nbuckets = 0;
    uint32_t symoffset = 0;
    uint32_t bloom_size = 0;
    uint32_t bloom_shift = 0;
  };
  uint32_t num_symbols = 0;
  // Read enogh data for the DT_GNU_HASH header so we can extract the values.
  if (auto data = ReadDataFromDynamic(gnu_hash, sizeof(DtGnuHashHeader))) {
    offset_t offset = 0;
    DtGnuHashHeader header;
    header.nbuckets = data->GetU32(&offset);
    header.symoffset = data->GetU32(&offset);
    header.bloom_size = data->GetU32(&offset);
    header.bloom_shift = data->GetU32(&offset);
    const size_t addr_size = GetAddressByteSize();
    const addr_t buckets_offset =
        sizeof(DtGnuHashHeader) + addr_size * header.bloom_size;
    std::vector<uint32_t> buckets;
    if (auto bucket_data = ReadDataFromDynamic(gnu_hash, header.nbuckets * 4,
                                               buckets_offset)) {
      offset = 0;
      for (uint32_t i = 0; i < header.nbuckets; ++i)
        buckets.push_back(bucket_data->GetU32(&offset));
      // Locate the chain that handles the largest index bucket.
      uint32_t last_symbol = 0;
      for (uint32_t bucket_value : buckets)
        last_symbol = std::max(bucket_value, last_symbol);
      if (last_symbol < header.symoffset) {
        num_symbols = header.symoffset;
      } else {
        // Walk the bucket's chain to add the chain length to the total.
        const addr_t chains_base_offset = buckets_offset + header.nbuckets * 4;
        for (;;) {
          if (auto chain_entry_data = ReadDataFromDynamic(
                  gnu_hash, 4,
                  chains_base_offset + (last_symbol - header.symoffset) * 4)) {
            offset = 0;
            uint32_t chain_entry = chain_entry_data->GetU32(&offset);
            ++last_symbol;
            // If the low bit is set, this entry is the end of the chain.
            if (chain_entry & 1)
              break;
          } else {
            break;
          }
        }
        num_symbols = last_symbol;
      }
    }
  }
  if (num_symbols > 0)
    return num_symbols;

  return std::nullopt;
}

std::optional<DataExtractor>
ObjectFileELF::GetDynsymDataFromDynamic(uint32_t &num_symbols) {
  // Every ELF file which represents an executable or shared library has
  // mandatory .dynamic entries. The DT_SYMTAB value contains a pointer to the
  // symbol table, and DT_SYMENT contains the size of a symbol table entry.
  // We then can use either the DT_HASH or DT_GNU_HASH to find the number of
  // symbols in the symbol table as the symbol count is not stored in the
  // .dynamic section as a key/value pair.
  //
  // When loading and ELF file from memory, only the program headers end up
  // being mapped into memory, and we can find these values in the PT_DYNAMIC
  // segment.
  num_symbols = 0;
  // Get the process in case this is an in memory ELF file.
  ProcessSP process_sp(m_process_wp.lock());
  const ELFDynamic *symtab = FindDynamicSymbol(DT_SYMTAB);
  const ELFDynamic *syment = FindDynamicSymbol(DT_SYMENT);
  // DT_SYMTAB and DT_SYMENT are mandatory.
  if (symtab == nullptr || syment == nullptr)
    return std::nullopt;

  if (std::optional<uint32_t> syms = GetNumSymbolsFromDynamicHash())
    num_symbols = *syms;
  else if (std::optional<uint32_t> syms = GetNumSymbolsFromDynamicGnuHash())
    num_symbols = *syms;
  else
    return std::nullopt;
  if (num_symbols == 0)
    return std::nullopt;
  return ReadDataFromDynamic(symtab, syment->d_val * num_symbols);
}
