1*d415bd75Srobert //=== DebugInfoLinker.cpp -------------------------------------------------===//
2*d415bd75Srobert //
3*d415bd75Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d415bd75Srobert // See https://llvm.org/LICENSE.txt for license information.
5*d415bd75Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d415bd75Srobert //
7*d415bd75Srobert //===----------------------------------------------------------------------===//
8*d415bd75Srobert
9*d415bd75Srobert #include "DebugInfoLinker.h"
10*d415bd75Srobert #include "Error.h"
11*d415bd75Srobert #include "llvm/ADT/StringSwitch.h"
12*d415bd75Srobert #include "llvm/DWARFLinker/DWARFLinker.h"
13*d415bd75Srobert #include "llvm/DWARFLinker/DWARFStreamer.h"
14*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFContext.h"
15*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
16*d415bd75Srobert #include "llvm/Object/ObjectFile.h"
17*d415bd75Srobert #include "llvm/Support/Endian.h"
18*d415bd75Srobert #include <memory>
19*d415bd75Srobert #include <vector>
20*d415bd75Srobert
21*d415bd75Srobert namespace llvm {
22*d415bd75Srobert namespace dwarfutil {
23*d415bd75Srobert
24*d415bd75Srobert // ObjFileAddressMap allows to check whether specified DIE referencing
25*d415bd75Srobert // dead addresses. It uses tombstone values to determine dead addresses.
26*d415bd75Srobert // The concrete values of tombstone constants were discussed in
27*d415bd75Srobert // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825.
28*d415bd75Srobert // So we use following values as indicators of dead addresses:
29*d415bd75Srobert //
30*d415bd75Srobert // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less))
31*d415bd75Srobert // or ([LowPC, HighPC] is not inside address ranges of .text sections).
32*d415bd75Srobert //
33*d415bd75Srobert // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less))
34*d415bd75Srobert // That value is assumed to be compatible with
35*d415bd75Srobert // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1
36*d415bd75Srobert //
37*d415bd75Srobert // exec: [LowPC, HighPC] is not inside address ranges of .text sections
38*d415bd75Srobert //
39*d415bd75Srobert // universal: maxpc and bfd
40*d415bd75Srobert class ObjFileAddressMap : public AddressesMap {
41*d415bd75Srobert public:
ObjFileAddressMap(DWARFContext & Context,const Options & Options,object::ObjectFile & ObjFile)42*d415bd75Srobert ObjFileAddressMap(DWARFContext &Context, const Options &Options,
43*d415bd75Srobert object::ObjectFile &ObjFile)
44*d415bd75Srobert : Opts(Options), Context(Context) {
45*d415bd75Srobert // Remember addresses of existing text sections.
46*d415bd75Srobert for (const object::SectionRef &Sect : ObjFile.sections()) {
47*d415bd75Srobert if (!Sect.isText())
48*d415bd75Srobert continue;
49*d415bd75Srobert const uint64_t Size = Sect.getSize();
50*d415bd75Srobert if (Size == 0)
51*d415bd75Srobert continue;
52*d415bd75Srobert const uint64_t StartAddr = Sect.getAddress();
53*d415bd75Srobert TextAddressRanges.insert({StartAddr, StartAddr + Size});
54*d415bd75Srobert }
55*d415bd75Srobert
56*d415bd75Srobert // Check CU address ranges for tombstone value.
57*d415bd75Srobert for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) {
58*d415bd75Srobert Expected<llvm::DWARFAddressRangesVector> ARanges =
59*d415bd75Srobert CU->getUnitDIE().getAddressRanges();
60*d415bd75Srobert if (ARanges) {
61*d415bd75Srobert for (auto &Range : *ARanges) {
62*d415bd75Srobert if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
63*d415bd75Srobert Options.Tombstone, CU->getAddressByteSize()))
64*d415bd75Srobert DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0);
65*d415bd75Srobert }
66*d415bd75Srobert }
67*d415bd75Srobert }
68*d415bd75Srobert }
69*d415bd75Srobert
70*d415bd75Srobert // should be renamed into has valid address ranges
hasValidRelocs()71*d415bd75Srobert bool hasValidRelocs() override { return !DWARFAddressRanges.empty(); }
72*d415bd75Srobert
isLiveSubprogram(const DWARFDie & DIE,CompileUnit::DIEInfo & Info)73*d415bd75Srobert bool isLiveSubprogram(const DWARFDie &DIE,
74*d415bd75Srobert CompileUnit::DIEInfo &Info) override {
75*d415bd75Srobert assert((DIE.getTag() == dwarf::DW_TAG_subprogram ||
76*d415bd75Srobert DIE.getTag() == dwarf::DW_TAG_label) &&
77*d415bd75Srobert "Wrong type of input die");
78*d415bd75Srobert
79*d415bd75Srobert if (std::optional<uint64_t> LowPC =
80*d415bd75Srobert dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) {
81*d415bd75Srobert if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(),
82*d415bd75Srobert Opts.Tombstone,
83*d415bd75Srobert DIE.getDwarfUnit()->getAddressByteSize())) {
84*d415bd75Srobert Info.AddrAdjust = 0;
85*d415bd75Srobert Info.InDebugMap = true;
86*d415bd75Srobert return true;
87*d415bd75Srobert }
88*d415bd75Srobert }
89*d415bd75Srobert
90*d415bd75Srobert return false;
91*d415bd75Srobert }
92*d415bd75Srobert
isLiveVariable(const DWARFDie & DIE,CompileUnit::DIEInfo & Info)93*d415bd75Srobert bool isLiveVariable(const DWARFDie &DIE,
94*d415bd75Srobert CompileUnit::DIEInfo &Info) override {
95*d415bd75Srobert assert((DIE.getTag() == dwarf::DW_TAG_variable ||
96*d415bd75Srobert DIE.getTag() == dwarf::DW_TAG_constant) &&
97*d415bd75Srobert "Wrong type of input die");
98*d415bd75Srobert
99*d415bd75Srobert if (Expected<DWARFLocationExpressionsVector> Loc =
100*d415bd75Srobert DIE.getLocations(dwarf::DW_AT_location)) {
101*d415bd75Srobert DWARFUnit *U = DIE.getDwarfUnit();
102*d415bd75Srobert for (const auto &Entry : *Loc) {
103*d415bd75Srobert DataExtractor Data(toStringRef(Entry.Expr),
104*d415bd75Srobert U->getContext().isLittleEndian(), 0);
105*d415bd75Srobert DWARFExpression Expression(Data, U->getAddressByteSize(),
106*d415bd75Srobert U->getFormParams().Format);
107*d415bd75Srobert bool HasLiveAddresses =
108*d415bd75Srobert any_of(Expression, [&](const DWARFExpression::Operation &Op) {
109*d415bd75Srobert // TODO: add handling of dwarf::DW_OP_addrx
110*d415bd75Srobert return !Op.isError() &&
111*d415bd75Srobert (Op.getCode() == dwarf::DW_OP_addr &&
112*d415bd75Srobert !isDeadAddress(Op.getRawOperand(0), U->getVersion(),
113*d415bd75Srobert Opts.Tombstone,
114*d415bd75Srobert DIE.getDwarfUnit()->getAddressByteSize()));
115*d415bd75Srobert });
116*d415bd75Srobert
117*d415bd75Srobert if (HasLiveAddresses) {
118*d415bd75Srobert Info.AddrAdjust = 0;
119*d415bd75Srobert Info.InDebugMap = true;
120*d415bd75Srobert return true;
121*d415bd75Srobert }
122*d415bd75Srobert }
123*d415bd75Srobert } else {
124*d415bd75Srobert // FIXME: missing DW_AT_location is OK here, but other errors should be
125*d415bd75Srobert // reported to the user.
126*d415bd75Srobert consumeError(Loc.takeError());
127*d415bd75Srobert }
128*d415bd75Srobert
129*d415bd75Srobert return false;
130*d415bd75Srobert }
131*d415bd75Srobert
applyValidRelocs(MutableArrayRef<char>,uint64_t,bool)132*d415bd75Srobert bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
133*d415bd75Srobert // no need to apply relocations to the linked binary.
134*d415bd75Srobert return false;
135*d415bd75Srobert }
136*d415bd75Srobert
getValidAddressRanges()137*d415bd75Srobert RangesTy &getValidAddressRanges() override { return DWARFAddressRanges; };
138*d415bd75Srobert
clear()139*d415bd75Srobert void clear() override { DWARFAddressRanges.clear(); }
140*d415bd75Srobert
relocateIndexedAddr(uint64_t StartOffset,uint64_t EndOffset)141*d415bd75Srobert llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
142*d415bd75Srobert uint64_t EndOffset) override {
143*d415bd75Srobert // No relocations in linked binary. Return just address value.
144*d415bd75Srobert
145*d415bd75Srobert const char *AddrPtr =
146*d415bd75Srobert Context.getDWARFObj().getAddrSection().Data.data() + StartOffset;
147*d415bd75Srobert support::endianness Endianess =
148*d415bd75Srobert Context.getDWARFObj().isLittleEndian() ? support::little : support::big;
149*d415bd75Srobert
150*d415bd75Srobert assert(EndOffset > StartOffset);
151*d415bd75Srobert switch (EndOffset - StartOffset) {
152*d415bd75Srobert case 1:
153*d415bd75Srobert return *AddrPtr;
154*d415bd75Srobert case 2:
155*d415bd75Srobert return support::endian::read16(AddrPtr, Endianess);
156*d415bd75Srobert case 4:
157*d415bd75Srobert return support::endian::read32(AddrPtr, Endianess);
158*d415bd75Srobert case 8:
159*d415bd75Srobert return support::endian::read64(AddrPtr, Endianess);
160*d415bd75Srobert }
161*d415bd75Srobert
162*d415bd75Srobert llvm_unreachable("relocateIndexedAddr unhandled case!");
163*d415bd75Srobert }
164*d415bd75Srobert
165*d415bd75Srobert protected:
166*d415bd75Srobert // returns true if specified address range is inside address ranges
167*d415bd75Srobert // of executable sections.
isInsideExecutableSectionsAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC)168*d415bd75Srobert bool isInsideExecutableSectionsAddressRange(uint64_t LowPC,
169*d415bd75Srobert std::optional<uint64_t> HighPC) {
170*d415bd75Srobert std::optional<AddressRange> Range =
171*d415bd75Srobert TextAddressRanges.getRangeThatContains(LowPC);
172*d415bd75Srobert
173*d415bd75Srobert if (HighPC)
174*d415bd75Srobert return Range.has_value() && Range->end() >= *HighPC;
175*d415bd75Srobert
176*d415bd75Srobert return Range.has_value();
177*d415bd75Srobert }
178*d415bd75Srobert
isBFDDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version)179*d415bd75Srobert uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
180*d415bd75Srobert uint16_t Version) {
181*d415bd75Srobert if (LowPC == 0)
182*d415bd75Srobert return true;
183*d415bd75Srobert
184*d415bd75Srobert if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1))
185*d415bd75Srobert return true;
186*d415bd75Srobert
187*d415bd75Srobert return !isInsideExecutableSectionsAddressRange(LowPC, HighPC);
188*d415bd75Srobert }
189*d415bd75Srobert
isMAXPCDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version,uint8_t AddressByteSize)190*d415bd75Srobert uint64_t isMAXPCDeadAddressRange(uint64_t LowPC,
191*d415bd75Srobert std::optional<uint64_t> HighPC,
192*d415bd75Srobert uint16_t Version, uint8_t AddressByteSize) {
193*d415bd75Srobert if (Version <= 4 && HighPC) {
194*d415bd75Srobert if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1))
195*d415bd75Srobert return true;
196*d415bd75Srobert } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize))
197*d415bd75Srobert return true;
198*d415bd75Srobert
199*d415bd75Srobert if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC))
200*d415bd75Srobert warning("Address referencing invalid text section is not marked with "
201*d415bd75Srobert "tombstone value");
202*d415bd75Srobert
203*d415bd75Srobert return false;
204*d415bd75Srobert }
205*d415bd75Srobert
isDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version,TombstoneKind Tombstone,uint8_t AddressByteSize)206*d415bd75Srobert bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
207*d415bd75Srobert uint16_t Version, TombstoneKind Tombstone,
208*d415bd75Srobert uint8_t AddressByteSize) {
209*d415bd75Srobert switch (Tombstone) {
210*d415bd75Srobert case TombstoneKind::BFD:
211*d415bd75Srobert return isBFDDeadAddressRange(LowPC, HighPC, Version);
212*d415bd75Srobert case TombstoneKind::MaxPC:
213*d415bd75Srobert return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize);
214*d415bd75Srobert case TombstoneKind::Universal:
215*d415bd75Srobert return isBFDDeadAddressRange(LowPC, HighPC, Version) ||
216*d415bd75Srobert isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize);
217*d415bd75Srobert case TombstoneKind::Exec:
218*d415bd75Srobert return !isInsideExecutableSectionsAddressRange(LowPC, HighPC);
219*d415bd75Srobert }
220*d415bd75Srobert
221*d415bd75Srobert llvm_unreachable("Unknown tombstone value");
222*d415bd75Srobert }
223*d415bd75Srobert
isDeadAddress(uint64_t LowPC,uint16_t Version,TombstoneKind Tombstone,uint8_t AddressByteSize)224*d415bd75Srobert bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone,
225*d415bd75Srobert uint8_t AddressByteSize) {
226*d415bd75Srobert return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone,
227*d415bd75Srobert AddressByteSize);
228*d415bd75Srobert }
229*d415bd75Srobert
230*d415bd75Srobert private:
231*d415bd75Srobert RangesTy DWARFAddressRanges;
232*d415bd75Srobert AddressRanges TextAddressRanges;
233*d415bd75Srobert const Options &Opts;
234*d415bd75Srobert DWARFContext &Context;
235*d415bd75Srobert };
236*d415bd75Srobert
knownByDWARFUtil(StringRef SecName)237*d415bd75Srobert static bool knownByDWARFUtil(StringRef SecName) {
238*d415bd75Srobert return llvm::StringSwitch<bool>(SecName)
239*d415bd75Srobert .Case(".debug_info", true)
240*d415bd75Srobert .Case(".debug_types", true)
241*d415bd75Srobert .Case(".debug_abbrev", true)
242*d415bd75Srobert .Case(".debug_loc", true)
243*d415bd75Srobert .Case(".debug_loclists", true)
244*d415bd75Srobert .Case(".debug_frame", true)
245*d415bd75Srobert .Case(".debug_aranges", true)
246*d415bd75Srobert .Case(".debug_ranges", true)
247*d415bd75Srobert .Case(".debug_rnglists", true)
248*d415bd75Srobert .Case(".debug_line", true)
249*d415bd75Srobert .Case(".debug_line_str", true)
250*d415bd75Srobert .Case(".debug_addr", true)
251*d415bd75Srobert .Case(".debug_macro", true)
252*d415bd75Srobert .Case(".debug_macinfo", true)
253*d415bd75Srobert .Case(".debug_str", true)
254*d415bd75Srobert .Case(".debug_str_offsets", true)
255*d415bd75Srobert .Case(".debug_pubnames", true)
256*d415bd75Srobert .Case(".debug_pubtypes", true)
257*d415bd75Srobert .Case(".debug_names", true)
258*d415bd75Srobert .Default(false);
259*d415bd75Srobert }
260*d415bd75Srobert
261*d415bd75Srobert static std::optional<DwarfLinkerAccelTableKind>
getAcceleratorTableKind(StringRef SecName)262*d415bd75Srobert getAcceleratorTableKind(StringRef SecName) {
263*d415bd75Srobert return llvm::StringSwitch<std::optional<DwarfLinkerAccelTableKind>>(SecName)
264*d415bd75Srobert .Case(".debug_pubnames", DwarfLinkerAccelTableKind::Pub)
265*d415bd75Srobert .Case(".debug_pubtypes", DwarfLinkerAccelTableKind::Pub)
266*d415bd75Srobert .Case(".debug_names", DwarfLinkerAccelTableKind::DebugNames)
267*d415bd75Srobert .Default(std::nullopt);
268*d415bd75Srobert }
269*d415bd75Srobert
getMessageForReplacedAcceleratorTables(SmallVector<StringRef> & AccelTableNamesToReplace,DwarfUtilAccelKind TargetTable)270*d415bd75Srobert static std::string getMessageForReplacedAcceleratorTables(
271*d415bd75Srobert SmallVector<StringRef> &AccelTableNamesToReplace,
272*d415bd75Srobert DwarfUtilAccelKind TargetTable) {
273*d415bd75Srobert std::string Message;
274*d415bd75Srobert
275*d415bd75Srobert Message += "'";
276*d415bd75Srobert for (StringRef Name : AccelTableNamesToReplace) {
277*d415bd75Srobert if (Message.size() > 1)
278*d415bd75Srobert Message += ", ";
279*d415bd75Srobert Message += Name;
280*d415bd75Srobert }
281*d415bd75Srobert
282*d415bd75Srobert Message += "' will be replaced with requested ";
283*d415bd75Srobert
284*d415bd75Srobert switch (TargetTable) {
285*d415bd75Srobert case DwarfUtilAccelKind::DWARF:
286*d415bd75Srobert Message += ".debug_names table";
287*d415bd75Srobert break;
288*d415bd75Srobert
289*d415bd75Srobert default:
290*d415bd75Srobert assert(false);
291*d415bd75Srobert }
292*d415bd75Srobert
293*d415bd75Srobert return Message;
294*d415bd75Srobert }
295*d415bd75Srobert
getMessageForDeletedAcceleratorTables(SmallVector<StringRef> & AccelTableNamesToReplace)296*d415bd75Srobert static std::string getMessageForDeletedAcceleratorTables(
297*d415bd75Srobert SmallVector<StringRef> &AccelTableNamesToReplace) {
298*d415bd75Srobert std::string Message;
299*d415bd75Srobert
300*d415bd75Srobert Message += "'";
301*d415bd75Srobert for (StringRef Name : AccelTableNamesToReplace) {
302*d415bd75Srobert if (Message.size() > 1)
303*d415bd75Srobert Message += ", ";
304*d415bd75Srobert Message += Name;
305*d415bd75Srobert }
306*d415bd75Srobert
307*d415bd75Srobert Message += "' will be deleted as no accelerator tables are requested";
308*d415bd75Srobert
309*d415bd75Srobert return Message;
310*d415bd75Srobert }
311*d415bd75Srobert
linkDebugInfo(object::ObjectFile & File,const Options & Options,raw_pwrite_stream & OutStream)312*d415bd75Srobert Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
313*d415bd75Srobert raw_pwrite_stream &OutStream) {
314*d415bd75Srobert
315*d415bd75Srobert auto ReportWarn = [&](const Twine &Message, StringRef Context,
316*d415bd75Srobert const DWARFDie *Die) {
317*d415bd75Srobert warning(Message, Context);
318*d415bd75Srobert
319*d415bd75Srobert if (!Options.Verbose || !Die)
320*d415bd75Srobert return;
321*d415bd75Srobert
322*d415bd75Srobert DIDumpOptions DumpOpts;
323*d415bd75Srobert DumpOpts.ChildRecurseDepth = 0;
324*d415bd75Srobert DumpOpts.Verbose = Options.Verbose;
325*d415bd75Srobert
326*d415bd75Srobert WithColor::note() << " in DIE:\n";
327*d415bd75Srobert Die->dump(errs(), /*Indent=*/6, DumpOpts);
328*d415bd75Srobert };
329*d415bd75Srobert auto ReportErr = [&](const Twine &Message, StringRef Context,
330*d415bd75Srobert const DWARFDie *) {
331*d415bd75Srobert WithColor::error(errs(), Context) << Message << '\n';
332*d415bd75Srobert };
333*d415bd75Srobert
334*d415bd75Srobert // Create output streamer.
335*d415bd75Srobert DwarfStreamer OutStreamer(OutputFileType::Object, OutStream, nullptr,
336*d415bd75Srobert ReportWarn, ReportWarn);
337*d415bd75Srobert Triple TargetTriple = File.makeTriple();
338*d415bd75Srobert if (!OutStreamer.init(TargetTriple, formatv("cannot create a stream for {0}",
339*d415bd75Srobert TargetTriple.getTriple())
340*d415bd75Srobert .str()))
341*d415bd75Srobert return createStringError(std::errc::invalid_argument, "");
342*d415bd75Srobert
343*d415bd75Srobert std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
344*d415bd75Srobert
345*d415bd75Srobert // Create DWARF linker.
346*d415bd75Srobert DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
347*d415bd75Srobert
348*d415bd75Srobert DebugInfoLinker.setEstimatedObjfilesAmount(1);
349*d415bd75Srobert DebugInfoLinker.setErrorHandler(ReportErr);
350*d415bd75Srobert DebugInfoLinker.setWarningHandler(ReportWarn);
351*d415bd75Srobert DebugInfoLinker.setNumThreads(Options.NumThreads);
352*d415bd75Srobert DebugInfoLinker.setNoODR(!Options.DoODRDeduplication);
353*d415bd75Srobert DebugInfoLinker.setVerbosity(Options.Verbose);
354*d415bd75Srobert DebugInfoLinker.setUpdate(!Options.DoGarbageCollection);
355*d415bd75Srobert
356*d415bd75Srobert std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1);
357*d415bd75Srobert std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
358*d415bd75Srobert std::vector<std::string> EmptyWarnings;
359*d415bd75Srobert
360*d415bd75Srobert // Add object files to the DWARFLinker.
361*d415bd75Srobert AddresssMapForLinking[0] =
362*d415bd75Srobert std::make_unique<ObjFileAddressMap>(*Context, Options, File);
363*d415bd75Srobert
364*d415bd75Srobert ObjectsForLinking[0] = std::make_unique<DWARFFile>(
365*d415bd75Srobert File.getFileName(), &*Context, AddresssMapForLinking[0].get(),
366*d415bd75Srobert EmptyWarnings);
367*d415bd75Srobert
368*d415bd75Srobert uint16_t MaxDWARFVersion = 0;
369*d415bd75Srobert std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
370*d415bd75Srobert [&MaxDWARFVersion](const DWARFUnit &Unit) {
371*d415bd75Srobert MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
372*d415bd75Srobert };
373*d415bd75Srobert
374*d415bd75Srobert for (size_t I = 0; I < ObjectsForLinking.size(); I++)
375*d415bd75Srobert DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr,
376*d415bd75Srobert OnCUDieLoaded);
377*d415bd75Srobert
378*d415bd75Srobert // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
379*d415bd75Srobert if (MaxDWARFVersion == 0)
380*d415bd75Srobert MaxDWARFVersion = 3;
381*d415bd75Srobert
382*d415bd75Srobert if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion))
383*d415bd75Srobert return Err;
384*d415bd75Srobert
385*d415bd75Srobert SmallVector<DwarfLinkerAccelTableKind> AccelTables;
386*d415bd75Srobert
387*d415bd75Srobert switch (Options.AccelTableKind) {
388*d415bd75Srobert case DwarfUtilAccelKind::None:
389*d415bd75Srobert // Nothing to do.
390*d415bd75Srobert break;
391*d415bd75Srobert case DwarfUtilAccelKind::DWARF:
392*d415bd75Srobert // use .debug_names for all DWARF versions.
393*d415bd75Srobert AccelTables.push_back(DwarfLinkerAccelTableKind::DebugNames);
394*d415bd75Srobert break;
395*d415bd75Srobert }
396*d415bd75Srobert
397*d415bd75Srobert // Add accelerator tables to DWARFLinker.
398*d415bd75Srobert for (DwarfLinkerAccelTableKind Table : AccelTables)
399*d415bd75Srobert DebugInfoLinker.addAccelTableKind(Table);
400*d415bd75Srobert
401*d415bd75Srobert SmallVector<StringRef> AccelTableNamesToReplace;
402*d415bd75Srobert SmallVector<StringRef> AccelTableNamesToDelete;
403*d415bd75Srobert
404*d415bd75Srobert // Unknown debug sections or non-requested accelerator sections would be
405*d415bd75Srobert // removed. Display warning for such sections.
406*d415bd75Srobert for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
407*d415bd75Srobert if (isDebugSection(Sec.Name)) {
408*d415bd75Srobert std::optional<DwarfLinkerAccelTableKind> SrcAccelTableKind =
409*d415bd75Srobert getAcceleratorTableKind(Sec.Name);
410*d415bd75Srobert
411*d415bd75Srobert if (SrcAccelTableKind) {
412*d415bd75Srobert assert(knownByDWARFUtil(Sec.Name));
413*d415bd75Srobert
414*d415bd75Srobert if (Options.AccelTableKind == DwarfUtilAccelKind::None)
415*d415bd75Srobert AccelTableNamesToDelete.push_back(Sec.Name);
416*d415bd75Srobert else if (std::find(AccelTables.begin(), AccelTables.end(),
417*d415bd75Srobert *SrcAccelTableKind) == AccelTables.end())
418*d415bd75Srobert AccelTableNamesToReplace.push_back(Sec.Name);
419*d415bd75Srobert } else if (!knownByDWARFUtil(Sec.Name)) {
420*d415bd75Srobert assert(!SrcAccelTableKind);
421*d415bd75Srobert warning(
422*d415bd75Srobert formatv("'{0}' is not currently supported: section will be skipped",
423*d415bd75Srobert Sec.Name),
424*d415bd75Srobert Options.InputFileName);
425*d415bd75Srobert }
426*d415bd75Srobert }
427*d415bd75Srobert }
428*d415bd75Srobert
429*d415bd75Srobert // Display message for the replaced accelerator tables.
430*d415bd75Srobert if (!AccelTableNamesToReplace.empty())
431*d415bd75Srobert warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
432*d415bd75Srobert Options.AccelTableKind),
433*d415bd75Srobert Options.InputFileName);
434*d415bd75Srobert
435*d415bd75Srobert // Display message for the removed accelerator tables.
436*d415bd75Srobert if (!AccelTableNamesToDelete.empty())
437*d415bd75Srobert warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
438*d415bd75Srobert Options.InputFileName);
439*d415bd75Srobert
440*d415bd75Srobert // Link debug info.
441*d415bd75Srobert if (Error Err = DebugInfoLinker.link())
442*d415bd75Srobert return Err;
443*d415bd75Srobert
444*d415bd75Srobert OutStreamer.finish();
445*d415bd75Srobert return Error::success();
446*d415bd75Srobert }
447*d415bd75Srobert
448*d415bd75Srobert } // end of namespace dwarfutil
449*d415bd75Srobert } // end of namespace llvm
450