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"
121db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinker.h"
131db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
141db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Parallel/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"
18fcaf7f86SDimitry Andric #include <memory>
19fcaf7f86SDimitry Andric #include <vector>
20fcaf7f86SDimitry Andric 
21fcaf7f86SDimitry Andric namespace llvm {
221db9f3b2SDimitry Andric using namespace dwarf_linker;
231db9f3b2SDimitry Andric 
24fcaf7f86SDimitry Andric namespace dwarfutil {
25fcaf7f86SDimitry Andric 
26fcaf7f86SDimitry Andric // ObjFileAddressMap allows to check whether specified DIE referencing
27fcaf7f86SDimitry Andric // dead addresses. It uses tombstone values to determine dead addresses.
28fcaf7f86SDimitry Andric // The concrete values of tombstone constants were discussed in
29fcaf7f86SDimitry Andric // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825.
30fcaf7f86SDimitry Andric // So we use following values as indicators of dead addresses:
31fcaf7f86SDimitry Andric //
32fcaf7f86SDimitry Andric // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and  DWARF v4 (or less))
33fcaf7f86SDimitry Andric //      or ([LowPC, HighPC] is not inside address ranges of .text sections).
34fcaf7f86SDimitry Andric //
35fcaf7f86SDimitry Andric // maxpc: (LowPC == -1) or (LowPC == -2 and  DWARF v4 (or less))
36fcaf7f86SDimitry Andric //        That value is assumed to be compatible with
37fcaf7f86SDimitry Andric //        http://www.dwarfstd.org/ShowIssue.php?issue=200609.1
38fcaf7f86SDimitry Andric //
39fcaf7f86SDimitry Andric // exec: [LowPC, HighPC] is not inside address ranges of .text sections
40fcaf7f86SDimitry Andric //
41fcaf7f86SDimitry Andric // universal: maxpc and bfd
421db9f3b2SDimitry Andric class ObjFileAddressMap : public AddressesMap {
43fcaf7f86SDimitry Andric public:
ObjFileAddressMap(DWARFContext & Context,const Options & Options,object::ObjectFile & ObjFile)44fcaf7f86SDimitry Andric   ObjFileAddressMap(DWARFContext &Context, const Options &Options,
45fcaf7f86SDimitry Andric                     object::ObjectFile &ObjFile)
4606c3fb27SDimitry 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();
6206c3fb27SDimitry Andric       if (!ARanges) {
6306c3fb27SDimitry Andric         llvm::consumeError(ARanges.takeError());
6406c3fb27SDimitry Andric         continue;
6506c3fb27SDimitry Andric       }
6606c3fb27SDimitry Andric 
67fcaf7f86SDimitry Andric       for (auto &Range : *ARanges) {
68fcaf7f86SDimitry Andric         if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(),
6906c3fb27SDimitry Andric                                 Options.Tombstone, CU->getAddressByteSize())) {
7006c3fb27SDimitry Andric           HasValidAddressRanges = true;
7106c3fb27SDimitry Andric           break;
72fcaf7f86SDimitry Andric         }
73fcaf7f86SDimitry Andric       }
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric       if (HasValidAddressRanges)
7606c3fb27SDimitry Andric         break;
77fcaf7f86SDimitry Andric     }
78fcaf7f86SDimitry Andric   }
79fcaf7f86SDimitry Andric 
80fcaf7f86SDimitry Andric   // should be renamed into has valid address ranges
hasValidRelocs()8106c3fb27SDimitry Andric   bool hasValidRelocs() override { return HasValidAddressRanges; }
82fcaf7f86SDimitry Andric 
getSubprogramRelocAdjustment(const DWARFDie & DIE,bool Verbose)83*7a6dacacSDimitry Andric   std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE,
84*7a6dacacSDimitry Andric                                                       bool Verbose) 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,
9306c3fb27SDimitry Andric                          DIE.getDwarfUnit()->getAddressByteSize()))
9406c3fb27SDimitry Andric         // Relocation value for the linked binary is 0.
9506c3fb27SDimitry Andric         return 0;
96fcaf7f86SDimitry Andric     }
97fcaf7f86SDimitry Andric 
9806c3fb27SDimitry Andric     return std::nullopt;
99fcaf7f86SDimitry Andric   }
100fcaf7f86SDimitry Andric 
1015f757f3fSDimitry Andric   std::optional<int64_t>
getExprOpAddressRelocAdjustment(DWARFUnit & U,const DWARFExpression::Operation & Op,uint64_t,uint64_t,bool Verbose)1025f757f3fSDimitry Andric   getExprOpAddressRelocAdjustment(DWARFUnit &U,
1035f757f3fSDimitry Andric                                   const DWARFExpression::Operation &Op,
104*7a6dacacSDimitry Andric                                   uint64_t, uint64_t, bool Verbose) override {
10506c3fb27SDimitry Andric     switch (Op.getCode()) {
10606c3fb27SDimitry Andric     default: {
10706c3fb27SDimitry Andric       assert(false && "Specified operation does not have address operand");
10806c3fb27SDimitry Andric     } break;
1095f757f3fSDimitry Andric     case dwarf::DW_OP_const2u:
11006c3fb27SDimitry Andric     case dwarf::DW_OP_const4u:
11106c3fb27SDimitry Andric     case dwarf::DW_OP_const8u:
1125f757f3fSDimitry Andric     case dwarf::DW_OP_const2s:
11306c3fb27SDimitry Andric     case dwarf::DW_OP_const4s:
11406c3fb27SDimitry Andric     case dwarf::DW_OP_const8s:
11506c3fb27SDimitry Andric     case dwarf::DW_OP_addr: {
11606c3fb27SDimitry Andric       if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone,
11706c3fb27SDimitry Andric                          U.getAddressByteSize()))
11806c3fb27SDimitry Andric         // Relocation value for the linked binary is 0.
11906c3fb27SDimitry Andric         return 0;
12006c3fb27SDimitry Andric     } break;
12106c3fb27SDimitry Andric     case dwarf::DW_OP_constx:
12206c3fb27SDimitry Andric     case dwarf::DW_OP_addrx: {
12306c3fb27SDimitry Andric       if (std::optional<object::SectionedAddress> Address =
12406c3fb27SDimitry Andric               U.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
12506c3fb27SDimitry Andric         if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone,
12606c3fb27SDimitry Andric                            U.getAddressByteSize()))
12706c3fb27SDimitry Andric           // Relocation value for the linked binary is 0.
12806c3fb27SDimitry Andric           return 0;
129fcaf7f86SDimitry Andric       }
13006c3fb27SDimitry Andric     } break;
131fcaf7f86SDimitry Andric     }
132fcaf7f86SDimitry Andric 
13306c3fb27SDimitry Andric     return std::nullopt;
134fcaf7f86SDimitry Andric   }
135fcaf7f86SDimitry Andric 
getLibraryInstallName()1365f757f3fSDimitry Andric   std::optional<StringRef> getLibraryInstallName() override {
1375f757f3fSDimitry Andric     return std::nullopt;
1385f757f3fSDimitry Andric   }
1395f757f3fSDimitry Andric 
applyValidRelocs(MutableArrayRef<char>,uint64_t,bool)140fcaf7f86SDimitry Andric   bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
141fcaf7f86SDimitry Andric     // no need to apply relocations to the linked binary.
142fcaf7f86SDimitry Andric     return false;
143fcaf7f86SDimitry Andric   }
144fcaf7f86SDimitry Andric 
needToSaveValidRelocs()1455f757f3fSDimitry Andric   bool needToSaveValidRelocs() override { return false; }
1465f757f3fSDimitry Andric 
updateAndSaveValidRelocs(bool,uint64_t,int64_t,uint64_t,uint64_t)1475f757f3fSDimitry Andric   void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t,
1485f757f3fSDimitry Andric                                 uint64_t) override {}
1495f757f3fSDimitry Andric 
updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,uint64_t OutputUnitOffset)1505f757f3fSDimitry Andric   void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
1515f757f3fSDimitry Andric                                        uint64_t OutputUnitOffset) override {}
1525f757f3fSDimitry Andric 
clear()15306c3fb27SDimitry Andric   void clear() override {}
154fcaf7f86SDimitry Andric 
155fcaf7f86SDimitry Andric protected:
156fcaf7f86SDimitry Andric   // returns true if specified address range is inside address ranges
157fcaf7f86SDimitry Andric   // of executable sections.
isInsideExecutableSectionsAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC)158fcaf7f86SDimitry Andric   bool isInsideExecutableSectionsAddressRange(uint64_t LowPC,
159bdd1243dSDimitry Andric                                               std::optional<uint64_t> HighPC) {
160bdd1243dSDimitry Andric     std::optional<AddressRange> Range =
161fcaf7f86SDimitry Andric         TextAddressRanges.getRangeThatContains(LowPC);
162fcaf7f86SDimitry Andric 
163fcaf7f86SDimitry Andric     if (HighPC)
164fcaf7f86SDimitry Andric       return Range.has_value() && Range->end() >= *HighPC;
165fcaf7f86SDimitry Andric 
166fcaf7f86SDimitry Andric     return Range.has_value();
167fcaf7f86SDimitry Andric   }
168fcaf7f86SDimitry Andric 
isBFDDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version)169bdd1243dSDimitry Andric   uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
170fcaf7f86SDimitry Andric                                  uint16_t Version) {
171fcaf7f86SDimitry Andric     if (LowPC == 0)
172fcaf7f86SDimitry Andric       return true;
173fcaf7f86SDimitry Andric 
174fcaf7f86SDimitry Andric     if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1))
175fcaf7f86SDimitry Andric       return true;
176fcaf7f86SDimitry Andric 
177fcaf7f86SDimitry Andric     return !isInsideExecutableSectionsAddressRange(LowPC, HighPC);
178fcaf7f86SDimitry Andric   }
179fcaf7f86SDimitry Andric 
isMAXPCDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version,uint8_t AddressByteSize)180bdd1243dSDimitry Andric   uint64_t isMAXPCDeadAddressRange(uint64_t LowPC,
181bdd1243dSDimitry Andric                                    std::optional<uint64_t> HighPC,
182fcaf7f86SDimitry Andric                                    uint16_t Version, uint8_t AddressByteSize) {
183fcaf7f86SDimitry Andric     if (Version <= 4 && HighPC) {
184fcaf7f86SDimitry Andric       if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1))
185fcaf7f86SDimitry Andric         return true;
186fcaf7f86SDimitry Andric     } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize))
187fcaf7f86SDimitry Andric       return true;
188fcaf7f86SDimitry Andric 
189fcaf7f86SDimitry Andric     if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC))
190fcaf7f86SDimitry Andric       warning("Address referencing invalid text section is not marked with "
191fcaf7f86SDimitry Andric               "tombstone value");
192fcaf7f86SDimitry Andric 
193fcaf7f86SDimitry Andric     return false;
194fcaf7f86SDimitry Andric   }
195fcaf7f86SDimitry Andric 
isDeadAddressRange(uint64_t LowPC,std::optional<uint64_t> HighPC,uint16_t Version,TombstoneKind Tombstone,uint8_t AddressByteSize)196bdd1243dSDimitry Andric   bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
197fcaf7f86SDimitry Andric                           uint16_t Version, TombstoneKind Tombstone,
198fcaf7f86SDimitry Andric                           uint8_t AddressByteSize) {
199fcaf7f86SDimitry Andric     switch (Tombstone) {
200fcaf7f86SDimitry Andric     case TombstoneKind::BFD:
201fcaf7f86SDimitry Andric       return isBFDDeadAddressRange(LowPC, HighPC, Version);
202fcaf7f86SDimitry Andric     case TombstoneKind::MaxPC:
203fcaf7f86SDimitry Andric       return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize);
204fcaf7f86SDimitry Andric     case TombstoneKind::Universal:
205fcaf7f86SDimitry Andric       return isBFDDeadAddressRange(LowPC, HighPC, Version) ||
206fcaf7f86SDimitry Andric              isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize);
207fcaf7f86SDimitry Andric     case TombstoneKind::Exec:
208fcaf7f86SDimitry Andric       return !isInsideExecutableSectionsAddressRange(LowPC, HighPC);
209fcaf7f86SDimitry Andric     }
210fcaf7f86SDimitry Andric 
211fcaf7f86SDimitry Andric     llvm_unreachable("Unknown tombstone value");
212fcaf7f86SDimitry Andric   }
213fcaf7f86SDimitry Andric 
isDeadAddress(uint64_t LowPC,uint16_t Version,TombstoneKind Tombstone,uint8_t AddressByteSize)214fcaf7f86SDimitry Andric   bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone,
215fcaf7f86SDimitry Andric                      uint8_t AddressByteSize) {
216bdd1243dSDimitry Andric     return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone,
217bdd1243dSDimitry Andric                               AddressByteSize);
218fcaf7f86SDimitry Andric   }
219fcaf7f86SDimitry Andric 
220fcaf7f86SDimitry Andric private:
221fcaf7f86SDimitry Andric   AddressRanges TextAddressRanges;
222fcaf7f86SDimitry Andric   const Options &Opts;
22306c3fb27SDimitry Andric   bool HasValidAddressRanges = false;
224fcaf7f86SDimitry Andric };
225fcaf7f86SDimitry Andric 
knownByDWARFUtil(StringRef SecName)226972a253aSDimitry Andric static bool knownByDWARFUtil(StringRef SecName) {
227972a253aSDimitry Andric   return llvm::StringSwitch<bool>(SecName)
228972a253aSDimitry Andric       .Case(".debug_info", true)
229972a253aSDimitry Andric       .Case(".debug_types", true)
230972a253aSDimitry Andric       .Case(".debug_abbrev", true)
231972a253aSDimitry Andric       .Case(".debug_loc", true)
232972a253aSDimitry Andric       .Case(".debug_loclists", true)
233972a253aSDimitry Andric       .Case(".debug_frame", true)
234972a253aSDimitry Andric       .Case(".debug_aranges", true)
235972a253aSDimitry Andric       .Case(".debug_ranges", true)
236972a253aSDimitry Andric       .Case(".debug_rnglists", true)
237972a253aSDimitry Andric       .Case(".debug_line", true)
238972a253aSDimitry Andric       .Case(".debug_line_str", true)
239972a253aSDimitry Andric       .Case(".debug_addr", true)
240972a253aSDimitry Andric       .Case(".debug_macro", true)
241972a253aSDimitry Andric       .Case(".debug_macinfo", true)
242972a253aSDimitry Andric       .Case(".debug_str", true)
243972a253aSDimitry Andric       .Case(".debug_str_offsets", true)
244bdd1243dSDimitry Andric       .Case(".debug_pubnames", true)
245bdd1243dSDimitry Andric       .Case(".debug_pubtypes", true)
246bdd1243dSDimitry Andric       .Case(".debug_names", true)
247972a253aSDimitry Andric       .Default(false);
248972a253aSDimitry Andric }
249972a253aSDimitry Andric 
25006c3fb27SDimitry Andric template <typename AccelTableKind>
25106c3fb27SDimitry Andric static std::optional<AccelTableKind>
getAcceleratorTableKind(StringRef SecName)252bdd1243dSDimitry Andric getAcceleratorTableKind(StringRef SecName) {
25306c3fb27SDimitry Andric   return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName)
25406c3fb27SDimitry Andric       .Case(".debug_pubnames", AccelTableKind::Pub)
25506c3fb27SDimitry Andric       .Case(".debug_pubtypes", AccelTableKind::Pub)
25606c3fb27SDimitry Andric       .Case(".debug_names", AccelTableKind::DebugNames)
257bdd1243dSDimitry Andric       .Default(std::nullopt);
258bdd1243dSDimitry Andric }
259bdd1243dSDimitry Andric 
getMessageForReplacedAcceleratorTables(SmallVector<StringRef> & AccelTableNamesToReplace,DwarfUtilAccelKind TargetTable)260bdd1243dSDimitry Andric static std::string getMessageForReplacedAcceleratorTables(
261bdd1243dSDimitry Andric     SmallVector<StringRef> &AccelTableNamesToReplace,
262bdd1243dSDimitry Andric     DwarfUtilAccelKind TargetTable) {
263bdd1243dSDimitry Andric   std::string Message;
264bdd1243dSDimitry Andric 
265bdd1243dSDimitry Andric   Message += "'";
266bdd1243dSDimitry Andric   for (StringRef Name : AccelTableNamesToReplace) {
267bdd1243dSDimitry Andric     if (Message.size() > 1)
268bdd1243dSDimitry Andric       Message += ", ";
269bdd1243dSDimitry Andric     Message += Name;
270bdd1243dSDimitry Andric   }
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric   Message += "' will be replaced with requested ";
273bdd1243dSDimitry Andric 
274bdd1243dSDimitry Andric   switch (TargetTable) {
275bdd1243dSDimitry Andric   case DwarfUtilAccelKind::DWARF:
276bdd1243dSDimitry Andric     Message += ".debug_names table";
277bdd1243dSDimitry Andric     break;
278bdd1243dSDimitry Andric 
279bdd1243dSDimitry Andric   default:
280bdd1243dSDimitry Andric     assert(false);
281bdd1243dSDimitry Andric   }
282bdd1243dSDimitry Andric 
283bdd1243dSDimitry Andric   return Message;
284bdd1243dSDimitry Andric }
285bdd1243dSDimitry Andric 
getMessageForDeletedAcceleratorTables(SmallVector<StringRef> & AccelTableNamesToReplace)286bdd1243dSDimitry Andric static std::string getMessageForDeletedAcceleratorTables(
287bdd1243dSDimitry Andric     SmallVector<StringRef> &AccelTableNamesToReplace) {
288bdd1243dSDimitry Andric   std::string Message;
289bdd1243dSDimitry Andric 
290bdd1243dSDimitry Andric   Message += "'";
291bdd1243dSDimitry Andric   for (StringRef Name : AccelTableNamesToReplace) {
292bdd1243dSDimitry Andric     if (Message.size() > 1)
293bdd1243dSDimitry Andric       Message += ", ";
294bdd1243dSDimitry Andric     Message += Name;
295bdd1243dSDimitry Andric   }
296bdd1243dSDimitry Andric 
297bdd1243dSDimitry Andric   Message += "' will be deleted as no accelerator tables are requested";
298bdd1243dSDimitry Andric 
299bdd1243dSDimitry Andric   return Message;
300bdd1243dSDimitry Andric }
301bdd1243dSDimitry Andric 
3021db9f3b2SDimitry Andric template <typename Linker>
linkDebugInfoImpl(object::ObjectFile & File,const Options & Options,raw_pwrite_stream & OutStream)30306c3fb27SDimitry Andric Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
304fcaf7f86SDimitry Andric                         raw_pwrite_stream &OutStream) {
3055f757f3fSDimitry Andric   std::mutex ErrorHandlerMutex;
3065f757f3fSDimitry Andric 
307fcaf7f86SDimitry Andric   auto ReportWarn = [&](const Twine &Message, StringRef Context,
308fcaf7f86SDimitry Andric                         const DWARFDie *Die) {
3095f757f3fSDimitry Andric     // FIXME: implement warning logging which does not block other threads.
3105f757f3fSDimitry Andric     if (!ErrorHandlerMutex.try_lock())
311fcaf7f86SDimitry Andric       return;
312fcaf7f86SDimitry Andric 
3135f757f3fSDimitry Andric     warning(Message, Context);
3145f757f3fSDimitry Andric     if (Options.Verbose && Die) {
315fcaf7f86SDimitry Andric       DIDumpOptions DumpOpts;
316fcaf7f86SDimitry Andric       DumpOpts.ChildRecurseDepth = 0;
317fcaf7f86SDimitry Andric       DumpOpts.Verbose = Options.Verbose;
318fcaf7f86SDimitry Andric 
319fcaf7f86SDimitry Andric       WithColor::note() << "    in DIE:\n";
320fcaf7f86SDimitry Andric       Die->dump(errs(), /*Indent=*/6, DumpOpts);
3215f757f3fSDimitry Andric     }
3225f757f3fSDimitry Andric     ErrorHandlerMutex.unlock();
323fcaf7f86SDimitry Andric   };
324fcaf7f86SDimitry Andric   auto ReportErr = [&](const Twine &Message, StringRef Context,
325fcaf7f86SDimitry Andric                        const DWARFDie *) {
3265f757f3fSDimitry Andric     // FIXME: implement error logging which does not block other threads.
3275f757f3fSDimitry Andric     if (!ErrorHandlerMutex.try_lock())
3285f757f3fSDimitry Andric       return;
3295f757f3fSDimitry Andric 
330fcaf7f86SDimitry Andric     WithColor::error(errs(), Context) << Message << '\n';
3315f757f3fSDimitry Andric     ErrorHandlerMutex.unlock();
332fcaf7f86SDimitry Andric   };
333fcaf7f86SDimitry Andric 
334fcaf7f86SDimitry Andric   // Create DWARF linker.
33506c3fb27SDimitry Andric   std::unique_ptr<Linker> DebugInfoLinker =
33606c3fb27SDimitry Andric       Linker::createLinker(ReportErr, ReportWarn);
337fcaf7f86SDimitry Andric 
33806c3fb27SDimitry Andric   Triple TargetTriple = File.makeTriple();
339*7a6dacacSDimitry Andric   std::unique_ptr<classic::DwarfStreamer> Streamer;
340*7a6dacacSDimitry Andric   if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr =
341*7a6dacacSDimitry Andric           classic::DwarfStreamer::createStreamer(
342*7a6dacacSDimitry Andric               TargetTriple, Linker::OutputFileType::Object, OutStream, nullptr,
343*7a6dacacSDimitry Andric               ReportWarn))
344*7a6dacacSDimitry Andric     Streamer = std::move(*StreamerOrErr);
345*7a6dacacSDimitry Andric   else
346*7a6dacacSDimitry Andric     return StreamerOrErr.takeError();
347*7a6dacacSDimitry Andric 
348*7a6dacacSDimitry Andric   if constexpr (std::is_same<Linker,
349*7a6dacacSDimitry Andric                              dwarf_linker::parallel::DWARFLinker>::value) {
350*7a6dacacSDimitry Andric     DebugInfoLinker->setOutputDWARFHandler(
351*7a6dacacSDimitry Andric         TargetTriple,
352*7a6dacacSDimitry Andric         [&](std::shared_ptr<dwarf_linker::parallel::SectionDescriptorBase>
353*7a6dacacSDimitry Andric                 Section) {
354*7a6dacacSDimitry Andric           Streamer->emitSectionContents(Section->getContents(),
355*7a6dacacSDimitry Andric                                         Section->getKind());
356*7a6dacacSDimitry Andric         });
357*7a6dacacSDimitry Andric   } else
358*7a6dacacSDimitry Andric     DebugInfoLinker->setOutputDWARFEmitter(Streamer.get());
359fcaf7f86SDimitry Andric 
36006c3fb27SDimitry Andric   DebugInfoLinker->setEstimatedObjfilesAmount(1);
36106c3fb27SDimitry Andric   DebugInfoLinker->setNumThreads(Options.NumThreads);
36206c3fb27SDimitry Andric   DebugInfoLinker->setNoODR(!Options.DoODRDeduplication);
36306c3fb27SDimitry Andric   DebugInfoLinker->setVerbosity(Options.Verbose);
36406c3fb27SDimitry Andric   DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection);
36506c3fb27SDimitry Andric 
3661db9f3b2SDimitry Andric   std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1);
367fcaf7f86SDimitry Andric 
368fcaf7f86SDimitry Andric   // Add object files to the DWARFLinker.
3695f757f3fSDimitry Andric   std::unique_ptr<DWARFContext> Context = DWARFContext::create(
3705f757f3fSDimitry Andric       File, DWARFContext::ProcessDebugRelocations::Process, nullptr, "",
3715f757f3fSDimitry Andric       [&](Error Err) {
3725f757f3fSDimitry Andric         handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
3735f757f3fSDimitry Andric           ReportErr(Info.message(), "", nullptr);
3745f757f3fSDimitry Andric         });
3755f757f3fSDimitry Andric       },
3765f757f3fSDimitry Andric       [&](Error Warning) {
3775f757f3fSDimitry Andric         handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
3785f757f3fSDimitry Andric           ReportWarn(Info.message(), "", nullptr);
3795f757f3fSDimitry Andric         });
3805f757f3fSDimitry Andric       });
3811db9f3b2SDimitry Andric   std::unique_ptr<ObjFileAddressMap> AddressesMap(
3821db9f3b2SDimitry Andric       std::make_unique<ObjFileAddressMap>(*Context, Options, File));
383fcaf7f86SDimitry Andric 
3841db9f3b2SDimitry Andric   ObjectsForLinking[0] = std::make_unique<DWARFFile>(
3855f757f3fSDimitry Andric       File.getFileName(), std::move(Context), std::move(AddressesMap));
386fcaf7f86SDimitry Andric 
387bdd1243dSDimitry Andric   uint16_t MaxDWARFVersion = 0;
388bdd1243dSDimitry Andric   std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
389bdd1243dSDimitry Andric       [&MaxDWARFVersion](const DWARFUnit &Unit) {
390bdd1243dSDimitry Andric         MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
391bdd1243dSDimitry Andric       };
392bdd1243dSDimitry Andric 
393fcaf7f86SDimitry Andric   for (size_t I = 0; I < ObjectsForLinking.size(); I++)
39406c3fb27SDimitry Andric     DebugInfoLinker->addObjectFile(*ObjectsForLinking[I], nullptr,
395bdd1243dSDimitry Andric                                    OnCUDieLoaded);
396bdd1243dSDimitry Andric 
397bdd1243dSDimitry Andric   // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
398bdd1243dSDimitry Andric   if (MaxDWARFVersion == 0)
399bdd1243dSDimitry Andric     MaxDWARFVersion = 3;
400bdd1243dSDimitry Andric 
40106c3fb27SDimitry Andric   if (Error Err = DebugInfoLinker->setTargetDWARFVersion(MaxDWARFVersion))
402bdd1243dSDimitry Andric     return Err;
403bdd1243dSDimitry Andric 
40406c3fb27SDimitry Andric   SmallVector<typename Linker::AccelTableKind> AccelTables;
405bdd1243dSDimitry Andric 
406bdd1243dSDimitry Andric   switch (Options.AccelTableKind) {
407bdd1243dSDimitry Andric   case DwarfUtilAccelKind::None:
408bdd1243dSDimitry Andric     // Nothing to do.
409bdd1243dSDimitry Andric     break;
410bdd1243dSDimitry Andric   case DwarfUtilAccelKind::DWARF:
411bdd1243dSDimitry Andric     // use .debug_names for all DWARF versions.
41206c3fb27SDimitry Andric     AccelTables.push_back(Linker::AccelTableKind::DebugNames);
413bdd1243dSDimitry Andric     break;
414bdd1243dSDimitry Andric   }
415bdd1243dSDimitry Andric 
416bdd1243dSDimitry Andric   // Add accelerator tables to DWARFLinker.
41706c3fb27SDimitry Andric   for (typename Linker::AccelTableKind Table : AccelTables)
41806c3fb27SDimitry Andric     DebugInfoLinker->addAccelTableKind(Table);
419bdd1243dSDimitry Andric 
4201db9f3b2SDimitry Andric   for (std::unique_ptr<DWARFFile> &CurFile : ObjectsForLinking) {
421bdd1243dSDimitry Andric     SmallVector<StringRef> AccelTableNamesToReplace;
422bdd1243dSDimitry Andric     SmallVector<StringRef> AccelTableNamesToDelete;
423bdd1243dSDimitry Andric 
424bdd1243dSDimitry Andric     // Unknown debug sections or non-requested accelerator sections would be
425bdd1243dSDimitry Andric     // removed. Display warning for such sections.
42606c3fb27SDimitry Andric     for (SectionName Sec : CurFile->Dwarf->getDWARFObj().getSectionNames()) {
427bdd1243dSDimitry Andric       if (isDebugSection(Sec.Name)) {
42806c3fb27SDimitry Andric         std::optional<typename Linker::AccelTableKind> SrcAccelTableKind =
42906c3fb27SDimitry Andric             getAcceleratorTableKind<typename Linker::AccelTableKind>(Sec.Name);
430bdd1243dSDimitry Andric 
431bdd1243dSDimitry Andric         if (SrcAccelTableKind) {
432bdd1243dSDimitry Andric           assert(knownByDWARFUtil(Sec.Name));
433bdd1243dSDimitry Andric 
434bdd1243dSDimitry Andric           if (Options.AccelTableKind == DwarfUtilAccelKind::None)
435bdd1243dSDimitry Andric             AccelTableNamesToDelete.push_back(Sec.Name);
43606c3fb27SDimitry Andric           else if (!llvm::is_contained(AccelTables, *SrcAccelTableKind))
437bdd1243dSDimitry Andric             AccelTableNamesToReplace.push_back(Sec.Name);
438bdd1243dSDimitry Andric         } else if (!knownByDWARFUtil(Sec.Name)) {
439bdd1243dSDimitry Andric           assert(!SrcAccelTableKind);
440bdd1243dSDimitry Andric           warning(
44106c3fb27SDimitry Andric               formatv(
44206c3fb27SDimitry Andric                   "'{0}' is not currently supported: section will be skipped",
443bdd1243dSDimitry Andric                   Sec.Name),
444bdd1243dSDimitry Andric               Options.InputFileName);
445bdd1243dSDimitry Andric         }
446bdd1243dSDimitry Andric       }
447bdd1243dSDimitry Andric     }
448bdd1243dSDimitry Andric 
449bdd1243dSDimitry Andric     // Display message for the replaced accelerator tables.
450bdd1243dSDimitry Andric     if (!AccelTableNamesToReplace.empty())
451bdd1243dSDimitry Andric       warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
452bdd1243dSDimitry Andric                                                      Options.AccelTableKind),
453bdd1243dSDimitry Andric               Options.InputFileName);
454bdd1243dSDimitry Andric 
455bdd1243dSDimitry Andric     // Display message for the removed accelerator tables.
456bdd1243dSDimitry Andric     if (!AccelTableNamesToDelete.empty())
457bdd1243dSDimitry Andric       warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
458bdd1243dSDimitry Andric               Options.InputFileName);
45906c3fb27SDimitry Andric   }
460fcaf7f86SDimitry Andric 
461fcaf7f86SDimitry Andric   // Link debug info.
46206c3fb27SDimitry Andric   if (Error Err = DebugInfoLinker->link())
463972a253aSDimitry Andric     return Err;
464972a253aSDimitry Andric 
465*7a6dacacSDimitry Andric   Streamer->finish();
466972a253aSDimitry Andric   return Error::success();
467fcaf7f86SDimitry Andric }
468fcaf7f86SDimitry Andric 
linkDebugInfo(object::ObjectFile & File,const Options & Options,raw_pwrite_stream & OutStream)46906c3fb27SDimitry Andric Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
47006c3fb27SDimitry Andric                     raw_pwrite_stream &OutStream) {
471*7a6dacacSDimitry Andric   if (Options.UseDWARFLinkerParallel)
4721db9f3b2SDimitry Andric     return linkDebugInfoImpl<parallel::DWARFLinker>(File, Options, OutStream);
47306c3fb27SDimitry Andric   else
4741db9f3b2SDimitry Andric     return linkDebugInfoImpl<classic::DWARFLinker>(File, Options, OutStream);
47506c3fb27SDimitry Andric }
47606c3fb27SDimitry Andric 
477fcaf7f86SDimitry Andric } // end of namespace dwarfutil
478fcaf7f86SDimitry Andric } // end of namespace llvm
479