//===- GdbIndex.cpp -------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // 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 "GdbIndex.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) { for (InputSectionBase *Sec : Obj->getSections()) { if (!Sec) continue; if (LLDDWARFSection *M = StringSwitch<LLDDWARFSection *>(Sec->Name) .Case(".debug_info", &InfoSection) .Case(".debug_ranges", &RangeSection) .Case(".debug_line", &LineSection) .Default(nullptr)) { Sec->maybeUncompress(); M->Data = toStringRef(Sec->Data); M->Sec = Sec; continue; } if (Sec->Name == ".debug_abbrev") AbbrevSection = toStringRef(Sec->Data); else if (Sec->Name == ".debug_gnu_pubnames") GnuPubNamesSection = toStringRef(Sec->Data); else if (Sec->Name == ".debug_gnu_pubtypes") GnuPubTypesSection = toStringRef(Sec->Data); else if (Sec->Name == ".debug_str") StrSection = toStringRef(Sec->Data); } } // 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 = std::lower_bound( Rels.begin(), Rels.end(), Pos, [](const RelTy &A, uint64_t B) { return A.r_offset < B; }); 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->getELFSyms()[SymIndex]; uint32_t SecIndex = File->getSectionIndex(Sym); // Broken debug info can point to a non-Defined symbol. auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel)); if (!DR) { error("unsupported relocation target while parsing debug info"); return None; } uint64_t Val = DR->Value + getAddend<ELFT>(Rel); // 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(); return RelocAddrEntry{SecIndex, Val}; } 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 elf::LLDDwarfObj<ELF32LE>; template class elf::LLDDwarfObj<ELF32BE>; template class elf::LLDDwarfObj<ELF64LE>; template class elf::LLDDwarfObj<ELF64BE>;