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