1 //===- DWARF.cpp ----------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // The -gdb-index option instructs the linker to emit a .gdb_index section. 10 // The section contains information to make gdb startup faster. 11 // The format of the section is described at 12 // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "DWARF.h" 17 #include "Symbols.h" 18 #include "Target.h" 19 #include "lld/Common/Memory.h" 20 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" 21 #include "llvm/Object/ELFObjectFile.h" 22 23 using namespace llvm; 24 using namespace llvm::object; 25 using namespace lld; 26 using namespace lld::elf; 27 28 template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) { 29 for (InputSectionBase *Sec : Obj->getSections()) { 30 if (!Sec) 31 continue; 32 33 if (LLDDWARFSection *M = 34 StringSwitch<LLDDWARFSection *>(Sec->Name) 35 .Case(".debug_addr", &AddrSection) 36 .Case(".debug_gnu_pubnames", &GnuPubNamesSection) 37 .Case(".debug_gnu_pubtypes", &GnuPubTypesSection) 38 .Case(".debug_info", &InfoSection) 39 .Case(".debug_ranges", &RangeSection) 40 .Case(".debug_rnglists", &RngListsSection) 41 .Case(".debug_line", &LineSection) 42 .Default(nullptr)) { 43 M->Data = toStringRef(Sec->data()); 44 M->Sec = Sec; 45 continue; 46 } 47 48 if (Sec->Name == ".debug_abbrev") 49 AbbrevSection = toStringRef(Sec->data()); 50 else if (Sec->Name == ".debug_str") 51 StrSection = toStringRef(Sec->data()); 52 else if (Sec->Name == ".debug_line_str") 53 LineStringSection = toStringRef(Sec->data()); 54 } 55 } 56 57 namespace { 58 template <class RelTy> struct LLDRelocationResolver { 59 // In the ELF ABIs, S sepresents the value of the symbol in the relocation 60 // entry. For Rela, the addend is stored as part of the relocation entry. 61 static uint64_t Resolve(object::RelocationRef Ref, uint64_t S, 62 uint64_t /* A */) { 63 return S + Ref.getRawDataRefImpl().p; 64 } 65 }; 66 67 template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> { 68 // For Rel, the addend A is supplied by the caller. 69 static uint64_t Resolve(object::RelocationRef /*Ref*/, uint64_t S, 70 uint64_t A) { 71 return S + A; 72 } 73 }; 74 } // namespace 75 76 // Find if there is a relocation at Pos in Sec. The code is a bit 77 // more complicated than usual because we need to pass a section index 78 // to llvm since it has no idea about InputSection. 79 template <class ELFT> 80 template <class RelTy> 81 Optional<RelocAddrEntry> 82 LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos, 83 ArrayRef<RelTy> Rels) const { 84 auto It = std::lower_bound( 85 Rels.begin(), Rels.end(), Pos, 86 [](const RelTy &A, uint64_t B) { return A.r_offset < B; }); 87 if (It == Rels.end() || It->r_offset != Pos) 88 return None; 89 const RelTy &Rel = *It; 90 91 const ObjFile<ELFT> *File = Sec.getFile<ELFT>(); 92 uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); 93 const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex]; 94 uint32_t SecIndex = File->getSectionIndex(Sym); 95 96 // Broken debug info can point to a non-Defined symbol. 97 auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel)); 98 if (!DR) { 99 RelType Type = Rel.getType(Config->IsMips64EL); 100 if (Type != Target->NoneRel) 101 error(toString(File) + ": relocation " + lld::toString(Type) + " at 0x" + 102 llvm::utohexstr(Rel.r_offset) + " has unsupported target"); 103 return None; 104 } 105 uint64_t Val = DR->Value; 106 107 // FIXME: We should be consistent about always adding the file 108 // offset or not. 109 if (DR->Section->Flags & ELF::SHF_ALLOC) 110 Val += cast<InputSection>(DR->Section)->getOffsetInFile(); 111 112 DataRefImpl D; 113 D.p = getAddend<ELFT>(Rel); 114 return RelocAddrEntry{SecIndex, RelocationRef(D, nullptr), 115 LLDRelocationResolver<RelTy>::Resolve, Val}; 116 } 117 118 template <class ELFT> 119 Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &S, 120 uint64_t Pos) const { 121 auto &Sec = static_cast<const LLDDWARFSection &>(S); 122 if (Sec.Sec->AreRelocsRela) 123 return findAux(*Sec.Sec, Pos, Sec.Sec->template relas<ELFT>()); 124 return findAux(*Sec.Sec, Pos, Sec.Sec->template rels<ELFT>()); 125 } 126 127 template class elf::LLDDwarfObj<ELF32LE>; 128 template class elf::LLDDwarfObj<ELF32BE>; 129 template class elf::LLDDwarfObj<ELF64LE>; 130 template class elf::LLDDwarfObj<ELF64BE>; 131