//===-- 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/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/Host/LZMA.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/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/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/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MipsABIFlags.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().GetPathAsConstString().GetCString(),
        lhs->GetByteSize(), rhs->GetByteSize());

  // 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 nul-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 nul 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 nul 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 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);

  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;
  default:
    ostype = llvm::Triple::OSType::UnknownOS;
  }
  return ostype != llvm::Triple::OSType::UnknownOS;
}

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

  const size_t initial_count = specs.GetSize();

  if (!extractor_sp || !extractor_sp->HasData())
    return 0;
  if (ObjectFileELF::MagicBytesMatch(extractor_sp->GetSharedDataBuffer(), 0,
                                     extractor_sp->GetByteSize())) {
    DataExtractor data;
    if (extractor_sp && extractor_sp->HasData()) {
      data = *extractor_sp->GetSubsetExtractorSP(data_offset);
      data_offset = 0;
    }
    elf::ELFHeader header;
    lldb::offset_t header_offset = data_offset;
    if (header.Parse(data, &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::VendorType vendor;
        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]));

        // SetArchitecture should have set the vendor to unknown
        vendor = spec.GetArchitecture().GetTriple().getVendor();
        assert(vendor == llvm::Triple::UnknownVendor);
        UNUSED_IF_ASSERT_DISABLED(vendor);

        //
        // 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 (data.GetByteSize() < length)
          if (DataBufferSP data_sp = MapFileData(file, length, file_offset)) {
            data.SetData(data_sp);
            data_offset = 0;
          }
        // 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 = data_offset;
          header.Parse(data, &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, data, 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().AsCString(), (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, data, header);

              core_notes_crc =
                  CalculateELFNotesSegmentsCRC32(program_headers, data);
            } else {
              gnu_debuglink_crc = calc_crc32(0, data);
            }
          }
          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));
          }
        }

        specs.Append(spec);
      }
    }
  }

  return specs.GetSize() - initial_count;
}

// 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(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(
            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 LLDB_INVALID_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 LLDB_INVALID_ADDRESS;
}

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;
      }
      }
    }
  }
}

// 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 ConstString 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;
        ConstString name(shstr_data.PeekCStr(I->sh_name));

        I->section_name = name;

        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 (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 ConstString 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(const char *name) {
  if (!name || !name[0] || !ParseSectionHeaders())
    return 0;
  for (size_t i = 1; i < m_section_headers.size(); ++i)
    if (m_section_headers[i].section_name == ConstString(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.GetStringRef());
}

static uint32_t GetTargetByteSize(SectionType Type, const ArchSpec &arch) {
  switch (Type) {
  case eSectionTypeData:
  case eSectionTypeZeroFill:
    return arch.GetDataByteSize();
  case eSectionTypeCode:
    return arch.GetCodeByteSize();
  default:
    return 1;
  }
}

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();
  ConstString 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()),
        ConstString(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;

    ConstString &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);

    const uint32_t target_bytes_size =
        GetTargetByteSize(sect_type, m_arch_spec);

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

    SectionSP section_sp(new 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.
        target_bytes_size)); // Number of host bytes per target byte

    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->GetID(),
                                              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(ConstString(".gnu_debugdata"));
  if (!section)
    return nullptr;

  if (!lldb_private::lzma::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 = lldb_private::lzma::uncompress(data.GetData(), uncompressedData);
  if (err) {
    GetModule()->ReportWarning(
        "An error occurred while decompression the section {0}: {1}",
        section->GetName().AsCString(), 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(const char *symbol_name) {
  if (!symbol_name)
    return '\0';

  const char *dollar_pos = ::strchr(symbol_name, '$');
  if (!dollar_pos || dollar_pos[1] == '\0')
    return '\0';

  if (dollar_pos[2] == '\0' || dollar_pos[2] == '.')
    return dollar_pos[1];
  return '\0';
}

static char FindRISCVMappingSymbol(const char *symbol_name) {
  if (!symbol_name)
    return '\0';

  if (strcmp(symbol_name, "$d") == 0) {
    return 'd';
  }
  if (strcmp(symbol_name, "$x") == 0) {
    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 ConstString text_section_name(".text");
  static ConstString init_section_name(".init");
  static ConstString fini_section_name(".fini");
  static ConstString ctors_section_name(".ctors");
  static ConstString dtors_section_name(".dtors");

  static ConstString data_section_name(".data");
  static ConstString rodata_section_name(".rodata");
  static ConstString rodata1_section_name(".rodata1");
  static ConstString data2_section_name(".data1");
  static ConstString bss_section_name(".bss");
  static ConstString opd_section_name(".opd"); // For ppc64

  // 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;

    const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
    if (!symbol_name)
      symbol_name = "";

    // 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 (llvm::StringRef(symbol_name).starts_with(".L"))
      continue;
    // No need to add non-section symbols that have no names
    if (symbol.getType() != STT_SECTION &&
        (symbol_name == nullptr || symbol_name[0] == '\0'))
      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 && (::strcmp(symbol_name, "oatdata") == 0 ||
                                 ::strcmp(symbol_name, "oatexec") == 0))
      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;
      }
    }

    if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION) {
      if (symbol_section_sp) {
        ConstString 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;
        }
      }
    }

    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;
    llvm::StringRef symbol_ref(symbol_name);

    // Symbol names may contain @VERSION suffixes. Find those and strip them
    // temporarily.
    size_t version_pos = symbol_ref.find('@');
    bool has_suffix = version_pos != llvm::StringRef::npos;
    llvm::StringRef symbol_bare = symbol_ref.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_ref.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;

    const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
    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);
}

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();
    DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
    // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
    WritableDataBuffer *data_buffer =
        llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
    void *const dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
                      ELFRelocation::RelocOffset64(rel);
    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);
    DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
    // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
    WritableDataBuffer *data_buffer =
        llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
    void *const dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
                      ELFRelocation::RelocOffset32(rel);
    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");
    DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
    // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
    WritableDataBuffer *data_buffer =
        llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
    uint8_t *dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
                   ELFRelocation::RelocOffset32(rel);
    // 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().AsCString(), 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().AsCString(), 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) {
            addr_t f_offset =
                rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
            DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
            // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
            WritableDataBuffer *data_buffer =
                llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
            uint32_t *dst = reinterpret_cast<uint32_t *>(
                data_buffer->GetBytes() + f_offset);

            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().AsCString(), 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().AsCString(), 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().AsCString("<Unknown>"));
  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(ConstString(".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=*/0,
          /*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().SetOffset(entry_point_addr.GetOffset() ^ 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 const char *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;

  const char *section_name = section->GetName().GetCString();
  // Can't relocate that which can't be named
  if (section_name == nullptr)
    return;

  // We don't relocate non-debug sections at the moment
  if (strncmp(section_name, debug_prefix, strlen(debug_prefix)))
    return;

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

  for (SectionHeaderCollIter I = m_section_headers.begin();
       I != m_section_headers.end(); ++I) {
    if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) {
      const char *hay_name = I->section_name.GetCString();
      if (hay_name == nullptr)
        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 char *section_name = I->section_name.AsCString("");
    if (section_name)
      *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->Printf("   %s\n", spec.GetFilename().GetCString());
    }
  }
}

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;
  }
#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)
// 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 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) {
        static ConstString 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().GetStringRef(),
      {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().GetCString(),
        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().GetCString(),
                               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);
}
