1 //===- DWARF.cpp ----------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
17 #include "InputSection.h"
19 #include "lld/Common/Memory.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
21 #include "llvm/Object/ELFObjectFile.h"
24 using namespace llvm::object
;
26 using namespace lld::elf
;
28 template <class ELFT
> LLDDwarfObj
<ELFT
>::LLDDwarfObj(ObjFile
<ELFT
> *obj
) {
29 // Get the ELF sections to retrieve sh_flags. See the SHF_GROUP comment below.
30 ArrayRef
<typename
ELFT::Shdr
> objSections
= obj
->template getELFShdrs
<ELFT
>();
31 assert(objSections
.size() == obj
->getSections().size());
32 for (auto [i
, sec
] : llvm::enumerate(obj
->getSections())) {
36 if (LLDDWARFSection
*m
=
37 StringSwitch
<LLDDWARFSection
*>(sec
->name
)
38 .Case(".debug_addr", &addrSection
)
39 .Case(".debug_gnu_pubnames", &gnuPubnamesSection
)
40 .Case(".debug_gnu_pubtypes", &gnuPubtypesSection
)
41 .Case(".debug_line", &lineSection
)
42 .Case(".debug_loclists", &loclistsSection
)
43 .Case(".debug_names", &namesSection
)
44 .Case(".debug_ranges", &rangesSection
)
45 .Case(".debug_rnglists", &rnglistsSection
)
46 .Case(".debug_str_offsets", &strOffsetsSection
)
48 m
->Data
= toStringRef(sec
->contentMaybeDecompress());
53 if (sec
->name
== ".debug_abbrev")
54 abbrevSection
= toStringRef(sec
->contentMaybeDecompress());
55 else if (sec
->name
== ".debug_str")
56 strSection
= toStringRef(sec
->contentMaybeDecompress());
57 else if (sec
->name
== ".debug_line_str")
58 lineStrSection
= toStringRef(sec
->contentMaybeDecompress());
59 else if (sec
->name
== ".debug_info" &&
60 !(objSections
[i
].sh_flags
& ELF::SHF_GROUP
)) {
61 // In DWARF v5, -fdebug-types-section places type units in .debug_info
62 // sections in COMDAT groups. They are not compile units and thus should
63 // be ignored for .gdb_index/diagnostics purposes.
65 // We use a simple heuristic: the compile unit does not have the SHF_GROUP
66 // flag. If we place compile units in COMDAT groups in the future, we may
67 // need to perform a lightweight parsing. We drop the SHF_GROUP flag when
68 // the InputSection was created, so we need to retrieve sh_flags from the
69 // associated ELF section header.
70 infoSection
.Data
= toStringRef(sec
->contentMaybeDecompress());
71 infoSection
.sec
= sec
;
77 template <class RelTy
> struct LLDRelocationResolver
{
78 // In the ELF ABIs, S sepresents the value of the symbol in the relocation
79 // entry. For Rela, the addend is stored as part of the relocation entry and
80 // is provided by the `findAux` method.
81 // In resolve() methods, the `type` and `offset` arguments would always be 0,
82 // because we don't set an owning object for the `RelocationRef` instance that
83 // we create in `findAux()`.
84 static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s
,
85 uint64_t /*locData*/, int64_t addend
) {
90 template <class ELFT
> struct LLDRelocationResolver
<Elf_Rel_Impl
<ELFT
, false>> {
91 // For Rel, the addend is extracted from the relocated location and is
92 // supplied by the caller.
93 static uint64_t resolve(uint64_t /*type*/, uint64_t /*offset*/, uint64_t s
,
94 uint64_t locData
, int64_t /*addend*/) {
100 // Find if there is a relocation at Pos in Sec. The code is a bit
101 // more complicated than usual because we need to pass a section index
102 // to llvm since it has no idea about InputSection.
103 template <class ELFT
>
104 template <class RelTy
>
105 std::optional
<RelocAddrEntry
>
106 LLDDwarfObj
<ELFT
>::findAux(const InputSectionBase
&sec
, uint64_t pos
,
107 ArrayRef
<RelTy
> rels
) const {
109 partition_point(rels
, [=](const RelTy
&a
) { return a
.r_offset
< pos
; });
110 if (it
== rels
.end() || it
->r_offset
!= pos
)
112 const RelTy
&rel
= *it
;
114 const ObjFile
<ELFT
> *file
= sec
.getFile
<ELFT
>();
115 Ctx
&ctx
= sec
.getCtx();
116 uint32_t symIndex
= rel
.getSymbol(ctx
.arg
.isMips64EL
);
117 const typename
ELFT::Sym
&sym
= file
->template getELFSyms
<ELFT
>()[symIndex
];
118 uint32_t secIndex
= file
->getSectionIndex(sym
);
120 // An undefined symbol may be a symbol defined in a discarded section. We
121 // shall still resolve it. This is important for --gdb-index: the end address
122 // offset of an entry in .debug_ranges is relocated. If it is not resolved,
123 // its zero value will terminate the decoding of .debug_ranges prematurely.
124 Symbol
&s
= file
->getRelocTargetSym(rel
);
126 if (auto *dr
= dyn_cast
<Defined
>(&s
))
130 d
.p
= getAddend
<ELFT
>(rel
);
131 return RelocAddrEntry
{secIndex
, RelocationRef(d
, nullptr),
132 val
, std::optional
<object::RelocationRef
>(),
133 0, LLDRelocationResolver
<RelTy
>::resolve
};
136 template <class ELFT
>
137 std::optional
<RelocAddrEntry
>
138 LLDDwarfObj
<ELFT
>::find(const llvm::DWARFSection
&s
, uint64_t pos
) const {
139 auto &sec
= static_cast<const LLDDWARFSection
&>(s
);
140 const RelsOrRelas
<ELFT
> rels
=
141 sec
.sec
->template relsOrRelas
<ELFT
>(/*supportsCrel=*/false);
142 if (rels
.areRelocsRel())
143 return findAux(*sec
.sec
, pos
, rels
.rels
);
144 return findAux(*sec
.sec
, pos
, rels
.relas
);
147 template class elf::LLDDwarfObj
<ELF32LE
>;
148 template class elf::LLDDwarfObj
<ELF32BE
>;
149 template class elf::LLDDwarfObj
<ELF64LE
>;
150 template class elf::LLDDwarfObj
<ELF64BE
>;