//===- 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 LLDDwarfObj::LLDDwarfObj(ObjFile *Obj) { for (InputSectionBase *Sec : Obj->getSections()) { if (!Sec) continue; if (LLDDWARFSection *M = StringSwitch(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 template Optional LLDDwarfObj::findAux(const InputSectionBase &Sec, uint64_t Pos, ArrayRef 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 *File = Sec.getFile(); 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(&File->getRelocTargetSym(Rel)); if (!DR) { error("unsupported relocation target while parsing debug info"); return None; } uint64_t Val = DR->Value + getAddend(Rel); // FIXME: We should be consistent about always adding the file // offset or not. if (DR->Section->Flags & ELF::SHF_ALLOC) Val += cast(DR->Section)->getOffsetInFile(); return RelocAddrEntry{SecIndex, Val}; } template Optional LLDDwarfObj::find(const llvm::DWARFSection &S, uint64_t Pos) const { auto &Sec = static_cast(S); if (Sec.Sec->AreRelocsRela) return findAux(*Sec.Sec, Pos, Sec.Sec->template relas()); return findAux(*Sec.Sec, Pos, Sec.Sec->template rels()); } template class elf::LLDDwarfObj; template class elf::LLDDwarfObj; template class elf::LLDDwarfObj; template class elf::LLDDwarfObj;