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