//===- DWARF.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
//
//===----------------------------------------------------------------------===//
//
// The --gdb-index option instructs the linker to emit a .gdb_index section.
// The section contains information to make gdb startup faster.
// The format of the section is described at
// https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html.
//
//===----------------------------------------------------------------------===//

#include "DWARF.h"
#include "InputSection.h"
#include "Symbols.h"
#include "lld/Common/Memory.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Object/ELFObjectFile.h"

using namespace llvm;
using namespace llvm::object;
using namespace lld;
using namespace lld::elf;

template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) {
  // Get the ELF sections to retrieve sh_flags. See the SHF_GROUP comment below.
  ArrayRef<typename ELFT::Shdr> objSections = obj->template getELFShdrs<ELFT>();
  assert(objSections.size() == obj->getSections().size());
  for (auto [i, sec] : llvm::enumerate(obj->getSections())) {
    if (!sec)
      continue;

    if (LLDDWARFSection *m =
            StringSwitch<LLDDWARFSection *>(sec->name)
                .Case(".debug_addr", &addrSection)
                .Case(".debug_gnu_pubnames", &gnuPubnamesSection)
                .Case(".debug_gnu_pubtypes", &gnuPubtypesSection)
                .Case(".debug_line", &lineSection)
                .Case(".debug_loclists", &loclistsSection)
                .Case(".debug_ranges", &rangesSection)
                .Case(".debug_rnglists", &rnglistsSection)
                .Case(".debug_str_offsets", &strOffsetsSection)
                .Default(nullptr)) {
      m->Data = toStringRef(sec->contentMaybeDecompress());
      m->sec = sec;
      continue;
    }

    if (sec->name == ".debug_abbrev")
      abbrevSection = toStringRef(sec->contentMaybeDecompress());
    else if (sec->name == ".debug_str")
      strSection = toStringRef(sec->contentMaybeDecompress());
    else if (sec->name == ".debug_line_str")
      lineStrSection = toStringRef(sec->contentMaybeDecompress());
    else if (sec->name == ".debug_info" &&
             !(objSections[i].sh_flags & ELF::SHF_GROUP)) {
      // In DWARF v5, -fdebug-types-section places type units in .debug_info
      // sections in COMDAT groups. They are not compile units and thus should
      // be ignored for .gdb_index/diagnostics purposes.
      //
      // We use a simple heuristic: the compile unit does not have the SHF_GROUP
      // flag. If we place compile units in COMDAT groups in the future, we may
      // need to perform a lightweight parsing. We drop the SHF_GROUP flag when
      // the InputSection was created, so we need to retrieve sh_flags from the
      // associated ELF section header.
      infoSection.Data = toStringRef(sec->contentMaybeDecompress());
      infoSection.sec = sec;
    }
  }
}

namespace {
template <class RelTy> struct LLDRelocationResolver {
  // In the ELF ABIs, S sepresents the value of the symbol in the relocation
  // entry. For Rela, the addend is stored as part of the relocation entry and
  // is provided by the `findAux` method.
  // In resolve() methods, the `type` and `offset` arguments would always be 0,
  // because we don't set an owning object for the `RelocationRef` instance that
  // we create in `findAux()`.
  static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s,
                          uint64_t /*locData*/, int64_t addend) {
    return s + addend;
  }
};

template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> {
  // For Rel, the addend is extracted from the relocated location and is
  // supplied by the caller.
  static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s,
                          uint64_t locData, int64_t /*addend*/) {
    return s + locData;
  }
};
} // namespace

// Find if there is a relocation at Pos in Sec.  The code is a bit
// more complicated than usual because we need to pass a section index
// to llvm since it has no idea about InputSection.
template <class ELFT>
template <class RelTy>
std::optional<RelocAddrEntry>
LLDDwarfObj<ELFT>::findAux(const InputSectionBase &sec, uint64_t pos,
                           ArrayRef<RelTy> rels) const {
  auto it =
      partition_point(rels, [=](const RelTy &a) { return a.r_offset < pos; });
  if (it == rels.end() || it->r_offset != pos)
    return std::nullopt;
  const RelTy &rel = *it;

  const ObjFile<ELFT> *file = sec.getFile<ELFT>();
  uint32_t symIndex = rel.getSymbol(config->isMips64EL);
  const typename ELFT::Sym &sym = file->template getELFSyms<ELFT>()[symIndex];
  uint32_t secIndex = file->getSectionIndex(sym);

  // An undefined symbol may be a symbol defined in a discarded section. We
  // shall still resolve it. This is important for --gdb-index: the end address
  // offset of an entry in .debug_ranges is relocated. If it is not resolved,
  // its zero value will terminate the decoding of .debug_ranges prematurely.
  Symbol &s = file->getRelocTargetSym(rel);
  uint64_t val = 0;
  if (auto *dr = dyn_cast<Defined>(&s))
    val = dr->value;

  DataRefImpl d;
  d.p = getAddend<ELFT>(rel);
  return RelocAddrEntry{secIndex, RelocationRef(d, nullptr),
                        val,      std::optional<object::RelocationRef>(),
                        0,        LLDRelocationResolver<RelTy>::resolve};
}

template <class ELFT>
std::optional<RelocAddrEntry>
LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &s, uint64_t pos) const {
  auto &sec = static_cast<const LLDDWARFSection &>(s);
  const RelsOrRelas<ELFT> rels = sec.sec->template relsOrRelas<ELFT>();
  if (rels.areRelocsRel())
    return findAux(*sec.sec, pos, rels.rels);
  return findAux(*sec.sec, pos, rels.relas);
}

template class elf::LLDDwarfObj<ELF32LE>;
template class elf::LLDDwarfObj<ELF32BE>;
template class elf::LLDDwarfObj<ELF64LE>;
template class elf::LLDDwarfObj<ELF64BE>;
