//===-- 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>();
    extractor_sp->SetData(buffer_sp, data_offset, buffer_sp->GetByteSize());
    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::DataBufferSP &data_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 (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) {
    DataExtractor data;
    data.SetData(data_sp);
    elf::ELFHeader header;
    lldb::offset_t header_offset = data_offset;
    if (header.Parse(data, &header_offset)) {
      if (data_sp) {
        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_sp 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_sp->GetByteSize() < length)
            data_sp = MapFileData(file, length, file_offset);
          if (data_sp)
            data.SetData(data_sp);
          // In case there is header extension in the section #0, the header we
          // parsed above could have sentinel values for e_phnum, e_shnum, and
          // e_shstrndx.  In this case we need to reparse the header with a
          // bigger data source to get the actual values.
          if (header.HasHeaderExtension()) {
            lldb::offset_t header_offset = 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.get(), &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.get());

      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.get());
      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.get(), 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.get(), 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) {
  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) {
  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);
  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;
    }
    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;

  DataExtractor rel_data;
  DataExtractor symtab_data;
  DataExtractor debug_data;

  if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) &&
      GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) &&
      GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) {
    ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr,
                     rel_data, symtab_data, debug_data, 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.get(), 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.get(), 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);
}
