reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
//===- 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 "Symbols.h"
#include "Target.h"
#include "lld/Common/Memory.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
#include "llvm/Object/ELFObjectFile.h"

using namespace llvm;
using namespace llvm::object;

namespace lld {
namespace elf {
template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) {
  for (InputSectionBase *sec : 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_info", &infoSection)
                .Case(".debug_ranges", &rangesSection)
                .Case(".debug_rnglists", &rnglistsSection)
                .Case(".debug_str_offsets", &strOffsetsSection)
                .Case(".debug_line", &lineSection)
                .Default(nullptr)) {
      m->Data = toStringRef(sec->data());
      m->sec = sec;
      continue;
    }

    if (sec->name == ".debug_abbrev")
      abbrevSection = toStringRef(sec->data());
    else if (sec->name == ".debug_str")
      strSection = toStringRef(sec->data());
    else if (sec->name == ".debug_line_str")
      lineStrSection = toStringRef(sec->data());
  }
}

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.
  static uint64_t resolve(object::RelocationRef ref, uint64_t s,
                          uint64_t /* A */) {
    return s + ref.getRawDataRefImpl().p;
  }
};

template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> {
  // For Rel, the addend A is supplied by the caller.
  static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s,
                          uint64_t a) {
    return s + a;
  }
};
} // 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>
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 None;
  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;

    // FIXME: We should be consistent about always adding the file
    // offset or not.
    if (dr->section->flags & ELF::SHF_ALLOC)
      val += cast<InputSection>(dr->section)->getOffsetInFile();
  }

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

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

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

} // namespace elf
} // namespace lld