xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- DWARFContext.cpp ---------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
10 #include "llvm/ADT/MapVector.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/BinaryFormat/Dwarf.h"
17 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
18 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
19 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
22 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
23 #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
24 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
27 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
28 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
29 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
30 #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
31 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
32 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
33 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
34 #include "llvm/DebugInfo/DWARF/DWARFListTable.h"
35 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
36 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
37 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
38 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
39 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
40 #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
41 #include "llvm/MC/TargetRegistry.h"
42 #include "llvm/Object/Decompressor.h"
43 #include "llvm/Object/MachO.h"
44 #include "llvm/Object/ObjectFile.h"
45 #include "llvm/Object/RelocationResolver.h"
46 #include "llvm/Support/Casting.h"
47 #include "llvm/Support/DataExtractor.h"
48 #include "llvm/Support/Error.h"
49 #include "llvm/Support/Format.h"
50 #include "llvm/Support/LEB128.h"
51 #include "llvm/Support/MemoryBuffer.h"
52 #include "llvm/Support/Path.h"
53 #include "llvm/Support/raw_ostream.h"
54 #include <cstdint>
55 #include <deque>
56 #include <map>
57 #include <string>
58 #include <utility>
59 #include <vector>
60 
61 using namespace llvm;
62 using namespace dwarf;
63 using namespace object;
64 
65 #define DEBUG_TYPE "dwarf"
66 
67 using DWARFLineTable = DWARFDebugLine::LineTable;
68 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
69 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
70 
71 
fixupIndexV4(DWARFContext & C,DWARFUnitIndex & Index)72 void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index) {
73   using EntryType = DWARFUnitIndex::Entry::SectionContribution;
74   using EntryMap = DenseMap<uint32_t, EntryType>;
75   EntryMap Map;
76   const auto &DObj = C.getDWARFObj();
77   if (DObj.getCUIndexSection().empty())
78     return;
79 
80   uint64_t Offset = 0;
81   uint32_t TruncOffset = 0;
82   DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
83     if (!(C.getParseCUTUIndexManually() ||
84           S.Data.size() >= std::numeric_limits<uint32_t>::max()))
85       return;
86 
87     DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
88     while (Data.isValidOffset(Offset)) {
89       DWARFUnitHeader Header;
90       if (Error ExtractionErr = Header.extract(
91               C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
92         C.getWarningHandler()(
93             createError("Failed to parse CU header in DWP file: " +
94                         toString(std::move(ExtractionErr))));
95         Map.clear();
96         break;
97       }
98 
99       auto Iter = Map.insert({TruncOffset,
100                               {Header.getOffset(), Header.getNextUnitOffset() -
101                                                        Header.getOffset()}});
102       if (!Iter.second) {
103         logAllUnhandledErrors(
104             createError("Collision occured between for truncated offset 0x" +
105                         Twine::utohexstr(TruncOffset)),
106             errs());
107         Map.clear();
108         return;
109       }
110 
111       Offset = Header.getNextUnitOffset();
112       TruncOffset = Offset;
113     }
114   });
115 
116   if (Map.empty())
117     return;
118 
119   for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
120     if (!E.isValid())
121       continue;
122     DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
123     auto Iter = Map.find(CUOff.getOffset());
124     if (Iter == Map.end()) {
125       logAllUnhandledErrors(createError("Could not find CU offset 0x" +
126                                         Twine::utohexstr(CUOff.getOffset()) +
127                                         " in the Map"),
128                             errs());
129       break;
130     }
131     CUOff.setOffset(Iter->second.getOffset());
132     if (CUOff.getOffset() != Iter->second.getOffset())
133       logAllUnhandledErrors(createError("Length of CU in CU index doesn't "
134                                         "match calculated length at offset 0x" +
135                                         Twine::utohexstr(CUOff.getOffset())),
136                             errs());
137   }
138 }
139 
fixupIndexV5(DWARFContext & C,DWARFUnitIndex & Index)140 void fixupIndexV5(DWARFContext &C, DWARFUnitIndex &Index) {
141   DenseMap<uint64_t, uint64_t> Map;
142 
143   const auto &DObj = C.getDWARFObj();
144   DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
145     if (!(C.getParseCUTUIndexManually() ||
146           S.Data.size() >= std::numeric_limits<uint32_t>::max()))
147       return;
148     DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
149     uint64_t Offset = 0;
150     while (Data.isValidOffset(Offset)) {
151       DWARFUnitHeader Header;
152       if (Error ExtractionErr = Header.extract(
153               C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
154         C.getWarningHandler()(
155             createError("Failed to parse CU header in DWP file: " +
156                         toString(std::move(ExtractionErr))));
157         break;
158       }
159       bool CU = Header.getUnitType() == DW_UT_split_compile;
160       uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash();
161       Map[Sig] = Header.getOffset();
162       Offset = Header.getNextUnitOffset();
163     }
164   });
165   if (Map.empty())
166     return;
167   for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
168     if (!E.isValid())
169       continue;
170     DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
171     auto Iter = Map.find(E.getSignature());
172     if (Iter == Map.end()) {
173       logAllUnhandledErrors(
174           createError("Could not find unit with signature 0x" +
175                       Twine::utohexstr(E.getSignature()) + " in the Map"),
176           errs());
177       break;
178     }
179     CUOff.setOffset(Iter->second);
180   }
181 }
182 
fixupIndex(DWARFContext & C,DWARFUnitIndex & Index)183 void fixupIndex(DWARFContext &C, DWARFUnitIndex &Index) {
184   if (Index.getVersion() < 5)
185     fixupIndexV4(C, Index);
186   else
187     fixupIndexV5(C, Index);
188 }
189 
190 template <typename T>
getAccelTable(std::unique_ptr<T> & Cache,const DWARFObject & Obj,const DWARFSection & Section,StringRef StringSection,bool IsLittleEndian)191 static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
192                         const DWARFSection &Section, StringRef StringSection,
193                         bool IsLittleEndian) {
194   if (Cache)
195     return *Cache;
196   DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
197   DataExtractor StrData(StringSection, IsLittleEndian, 0);
198   Cache = std::make_unique<T>(AccelSection, StrData);
199   if (Error E = Cache->extract())
200     llvm::consumeError(std::move(E));
201   return *Cache;
202 }
203 
204 
205 std::unique_ptr<DWARFDebugMacro>
parseMacroOrMacinfo(MacroSecType SectionType)206 DWARFContext::DWARFContextState::parseMacroOrMacinfo(MacroSecType SectionType) {
207   auto Macro = std::make_unique<DWARFDebugMacro>();
208   auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {
209     if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection
210                                                     ? D.compile_units()
211                                                     : D.dwo_compile_units(),
212                                                 SectionType == MacroSection
213                                                     ? D.getStringExtractor()
214                                                     : D.getStringDWOExtractor(),
215                                                 Data)
216                             : Macro->parseMacinfo(Data)) {
217       D.getRecoverableErrorHandler()(std::move(Err));
218       Macro = nullptr;
219     }
220   };
221   const DWARFObject &DObj = D.getDWARFObj();
222   switch (SectionType) {
223   case MacinfoSection: {
224     DWARFDataExtractor Data(DObj.getMacinfoSection(), D.isLittleEndian(), 0);
225     ParseAndDump(Data, /*IsMacro=*/false);
226     break;
227   }
228   case MacinfoDwoSection: {
229     DWARFDataExtractor Data(DObj.getMacinfoDWOSection(), D.isLittleEndian(), 0);
230     ParseAndDump(Data, /*IsMacro=*/false);
231     break;
232   }
233   case MacroSection: {
234     DWARFDataExtractor Data(DObj, DObj.getMacroSection(), D.isLittleEndian(),
235                             0);
236     ParseAndDump(Data, /*IsMacro=*/true);
237     break;
238   }
239   case MacroDwoSection: {
240     DWARFDataExtractor Data(DObj.getMacroDWOSection(), D.isLittleEndian(), 0);
241     ParseAndDump(Data, /*IsMacro=*/true);
242     break;
243   }
244   }
245   return Macro;
246 }
247 
248 namespace {
249 class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
250 
251   DWARFUnitVector NormalUnits;
252   std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits;
253   std::unique_ptr<DWARFUnitIndex> CUIndex;
254   std::unique_ptr<DWARFGdbIndex> GdbIndex;
255   std::unique_ptr<DWARFUnitIndex> TUIndex;
256   std::unique_ptr<DWARFDebugAbbrev> Abbrev;
257   std::unique_ptr<DWARFDebugLoc> Loc;
258   std::unique_ptr<DWARFDebugAranges> Aranges;
259   std::unique_ptr<DWARFDebugLine> Line;
260   std::unique_ptr<DWARFDebugFrame> DebugFrame;
261   std::unique_ptr<DWARFDebugFrame> EHFrame;
262   std::unique_ptr<DWARFDebugMacro> Macro;
263   std::unique_ptr<DWARFDebugMacro> Macinfo;
264   std::unique_ptr<DWARFDebugNames> Names;
265   std::unique_ptr<AppleAcceleratorTable> AppleNames;
266   std::unique_ptr<AppleAcceleratorTable> AppleTypes;
267   std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
268   std::unique_ptr<AppleAcceleratorTable> AppleObjC;
269   DWARFUnitVector DWOUnits;
270   std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits;
271   std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
272   std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
273   std::unique_ptr<DWARFDebugMacro> MacroDWO;
274   struct DWOFile {
275     object::OwningBinary<object::ObjectFile> File;
276     std::unique_ptr<DWARFContext> Context;
277   };
278   StringMap<std::weak_ptr<DWOFile>> DWOFiles;
279   std::weak_ptr<DWOFile> DWP;
280   bool CheckedForDWP = false;
281   std::string DWPName;
282 
283 public:
ThreadUnsafeDWARFContextState(DWARFContext & DC,std::string & DWP)284   ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :
285       DWARFContext::DWARFContextState(DC),
286       DWPName(std::move(DWP)) {}
287 
getNormalUnits()288   DWARFUnitVector &getNormalUnits() override {
289     if (NormalUnits.empty()) {
290       const DWARFObject &DObj = D.getDWARFObj();
291       DObj.forEachInfoSections([&](const DWARFSection &S) {
292         NormalUnits.addUnitsForSection(D, S, DW_SECT_INFO);
293       });
294       NormalUnits.finishedInfoUnits();
295       DObj.forEachTypesSections([&](const DWARFSection &S) {
296         NormalUnits.addUnitsForSection(D, S, DW_SECT_EXT_TYPES);
297       });
298     }
299     return NormalUnits;
300   }
301 
getDWOUnits(bool Lazy)302   DWARFUnitVector &getDWOUnits(bool Lazy) override {
303     if (DWOUnits.empty()) {
304       const DWARFObject &DObj = D.getDWARFObj();
305 
306       DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
307         DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_INFO, Lazy);
308       });
309       DWOUnits.finishedInfoUnits();
310       DObj.forEachTypesDWOSections([&](const DWARFSection &S) {
311         DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_EXT_TYPES, Lazy);
312       });
313     }
314     return DWOUnits;
315   }
316 
getDebugAbbrevDWO()317   const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
318     if (AbbrevDWO)
319       return AbbrevDWO.get();
320     const DWARFObject &DObj = D.getDWARFObj();
321     DataExtractor abbrData(DObj.getAbbrevDWOSection(), D.isLittleEndian(), 0);
322     AbbrevDWO = std::make_unique<DWARFDebugAbbrev>(abbrData);
323     return AbbrevDWO.get();
324   }
325 
getCUIndex()326   const DWARFUnitIndex &getCUIndex() override {
327     if (CUIndex)
328       return *CUIndex;
329 
330     DataExtractor Data(D.getDWARFObj().getCUIndexSection(),
331                        D.isLittleEndian(), 0);
332     CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
333     if (CUIndex->parse(Data))
334       fixupIndex(D, *CUIndex);
335     return *CUIndex;
336   }
getTUIndex()337   const DWARFUnitIndex &getTUIndex() override {
338     if (TUIndex)
339       return *TUIndex;
340 
341     DataExtractor Data(D.getDWARFObj().getTUIndexSection(),
342                        D.isLittleEndian(), 0);
343     TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
344     bool isParseSuccessful = TUIndex->parse(Data);
345     // If we are parsing TU-index and for .debug_types section we don't need
346     // to do anything.
347     if (isParseSuccessful && TUIndex->getVersion() != 2)
348       fixupIndex(D, *TUIndex);
349     return *TUIndex;
350   }
351 
getGdbIndex()352   DWARFGdbIndex &getGdbIndex() override {
353     if (GdbIndex)
354       return *GdbIndex;
355 
356     DataExtractor Data(D.getDWARFObj().getGdbIndexSection(), true /*LE*/, 0);
357     GdbIndex = std::make_unique<DWARFGdbIndex>();
358     GdbIndex->parse(Data);
359     return *GdbIndex;
360   }
361 
getDebugAbbrev()362   const DWARFDebugAbbrev *getDebugAbbrev() override {
363     if (Abbrev)
364       return Abbrev.get();
365 
366     DataExtractor Data(D.getDWARFObj().getAbbrevSection(),
367                        D.isLittleEndian(), 0);
368     Abbrev = std::make_unique<DWARFDebugAbbrev>(Data);
369     return Abbrev.get();
370   }
371 
getDebugLoc()372   const DWARFDebugLoc *getDebugLoc() override {
373     if (Loc)
374       return Loc.get();
375 
376     const DWARFObject &DObj = D.getDWARFObj();
377     // Assume all units have the same address byte size.
378     auto Data =
379         D.getNumCompileUnits()
380             ? DWARFDataExtractor(DObj, DObj.getLocSection(), D.isLittleEndian(),
381                                  D.getUnitAtIndex(0)->getAddressByteSize())
382             : DWARFDataExtractor("", D.isLittleEndian(), 0);
383     Loc = std::make_unique<DWARFDebugLoc>(std::move(Data));
384     return Loc.get();
385   }
386 
getDebugAranges()387   const DWARFDebugAranges *getDebugAranges() override {
388     if (Aranges)
389       return Aranges.get();
390 
391     Aranges = std::make_unique<DWARFDebugAranges>();
392     Aranges->generate(&D);
393     return Aranges.get();
394   }
395 
396   Expected<const DWARFDebugLine::LineTable *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)397   getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
398     if (!Line)
399       Line = std::make_unique<DWARFDebugLine>();
400 
401     auto UnitDIE = U->getUnitDIE();
402     if (!UnitDIE)
403       return nullptr;
404 
405     auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
406     if (!Offset)
407       return nullptr; // No line table for this compile unit.
408 
409     uint64_t stmtOffset = *Offset + U->getLineTableOffset();
410     // See if the line table is cached.
411     if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
412       return lt;
413 
414     // Make sure the offset is good before we try to parse.
415     if (stmtOffset >= U->getLineSection().Data.size())
416       return nullptr;
417 
418     // We have to parse it first.
419     DWARFDataExtractor Data(U->getContext().getDWARFObj(), U->getLineSection(),
420                             U->isLittleEndian(), U->getAddressByteSize());
421     return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U,
422                                      RecoverableErrorHandler);
423 
424   }
425 
clearLineTableForUnit(DWARFUnit * U)426   void clearLineTableForUnit(DWARFUnit *U) override {
427     if (!Line)
428       return;
429 
430     auto UnitDIE = U->getUnitDIE();
431     if (!UnitDIE)
432       return;
433 
434     auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
435     if (!Offset)
436       return;
437 
438     uint64_t stmtOffset = *Offset + U->getLineTableOffset();
439     Line->clearLineTable(stmtOffset);
440   }
441 
getDebugFrame()442   Expected<const DWARFDebugFrame *> getDebugFrame() override {
443     if (DebugFrame)
444       return DebugFrame.get();
445     const DWARFObject &DObj = D.getDWARFObj();
446     const DWARFSection &DS = DObj.getFrameSection();
447 
448     // There's a "bug" in the DWARFv3 standard with respect to the target address
449     // size within debug frame sections. While DWARF is supposed to be independent
450     // of its container, FDEs have fields with size being "target address size",
451     // which isn't specified in DWARF in general. It's only specified for CUs, but
452     // .eh_frame can appear without a .debug_info section. Follow the example of
453     // other tools (libdwarf) and extract this from the container (ObjectFile
454     // provides this information). This problem is fixed in DWARFv4
455     // See this dwarf-discuss discussion for more details:
456     // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
457     DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
458                             DObj.getAddressSize());
459     auto DF =
460         std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,
461                                           DS.Address);
462     if (Error E = DF->parse(Data))
463       return std::move(E);
464 
465     DebugFrame.swap(DF);
466     return DebugFrame.get();
467   }
468 
getEHFrame()469   Expected<const DWARFDebugFrame *> getEHFrame() override {
470     if (EHFrame)
471       return EHFrame.get();
472     const DWARFObject &DObj = D.getDWARFObj();
473 
474     const DWARFSection &DS = DObj.getEHFrameSection();
475     DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
476                             DObj.getAddressSize());
477     auto DF =
478         std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,
479                                           DS.Address);
480     if (Error E = DF->parse(Data))
481       return std::move(E);
482     EHFrame.swap(DF);
483     return EHFrame.get();
484   }
485 
getDebugMacinfo()486   const DWARFDebugMacro *getDebugMacinfo() override {
487     if (!Macinfo)
488       Macinfo = parseMacroOrMacinfo(MacinfoSection);
489     return Macinfo.get();
490   }
getDebugMacinfoDWO()491   const DWARFDebugMacro *getDebugMacinfoDWO() override {
492     if (!MacinfoDWO)
493       MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
494     return MacinfoDWO.get();
495   }
getDebugMacro()496   const DWARFDebugMacro *getDebugMacro() override {
497     if (!Macro)
498       Macro = parseMacroOrMacinfo(MacroSection);
499     return Macro.get();
500   }
getDebugMacroDWO()501   const DWARFDebugMacro *getDebugMacroDWO() override {
502     if (!MacroDWO)
503       MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
504     return MacroDWO.get();
505   }
getDebugNames()506   const DWARFDebugNames &getDebugNames() override {
507     const DWARFObject &DObj = D.getDWARFObj();
508     return getAccelTable(Names, DObj, DObj.getNamesSection(),
509                          DObj.getStrSection(), D.isLittleEndian());
510   }
getAppleNames()511   const AppleAcceleratorTable &getAppleNames() override {
512     const DWARFObject &DObj = D.getDWARFObj();
513     return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(),
514                          DObj.getStrSection(), D.isLittleEndian());
515 
516   }
getAppleTypes()517   const AppleAcceleratorTable &getAppleTypes() override {
518     const DWARFObject &DObj = D.getDWARFObj();
519     return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(),
520                          DObj.getStrSection(), D.isLittleEndian());
521 
522   }
getAppleNamespaces()523   const AppleAcceleratorTable &getAppleNamespaces() override {
524     const DWARFObject &DObj = D.getDWARFObj();
525     return getAccelTable(AppleNamespaces, DObj,
526                          DObj.getAppleNamespacesSection(),
527                          DObj.getStrSection(), D.isLittleEndian());
528 
529   }
getAppleObjC()530   const AppleAcceleratorTable &getAppleObjC() override {
531     const DWARFObject &DObj = D.getDWARFObj();
532     return getAccelTable(AppleObjC, DObj, DObj.getAppleObjCSection(),
533                          DObj.getStrSection(), D.isLittleEndian());
534   }
535 
536   std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)537   getDWOContext(StringRef AbsolutePath) override {
538     if (auto S = DWP.lock()) {
539       DWARFContext *Ctxt = S->Context.get();
540       return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
541     }
542 
543     std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
544 
545     if (auto S = Entry->lock()) {
546       DWARFContext *Ctxt = S->Context.get();
547       return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
548     }
549 
550     const DWARFObject &DObj = D.getDWARFObj();
551 
552     Expected<OwningBinary<ObjectFile>> Obj = [&] {
553       if (!CheckedForDWP) {
554         SmallString<128> DWPName;
555         auto Obj = object::ObjectFile::createObjectFile(
556             this->DWPName.empty()
557                 ? (DObj.getFileName() + ".dwp").toStringRef(DWPName)
558                 : StringRef(this->DWPName));
559         if (Obj) {
560           Entry = &DWP;
561           return Obj;
562         } else {
563           CheckedForDWP = true;
564           // TODO: Should this error be handled (maybe in a high verbosity mode)
565           // before falling back to .dwo files?
566           consumeError(Obj.takeError());
567         }
568       }
569 
570       return object::ObjectFile::createObjectFile(AbsolutePath);
571     }();
572 
573     if (!Obj) {
574       // TODO: Actually report errors helpfully.
575       consumeError(Obj.takeError());
576       return nullptr;
577     }
578 
579     auto S = std::make_shared<DWOFile>();
580     S->File = std::move(Obj.get());
581     // Allow multi-threaded access if there is a .dwp file as the CU index and
582     // TU index might be accessed from multiple threads.
583     bool ThreadSafe = isThreadSafe();
584     S->Context = DWARFContext::create(
585         *S->File.getBinary(), DWARFContext::ProcessDebugRelocations::Ignore,
586         nullptr, "", WithColor::defaultErrorHandler,
587         WithColor::defaultWarningHandler, ThreadSafe);
588     *Entry = S;
589     auto *Ctxt = S->Context.get();
590     return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
591   }
592 
isThreadSafe() const593   bool isThreadSafe() const override { return false; }
594 
getNormalTypeUnitMap()595   const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() {
596     if (!NormalTypeUnits) {
597       NormalTypeUnits.emplace();
598       for (const auto &U :D.normal_units()) {
599         if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
600           (*NormalTypeUnits)[TU->getTypeHash()] = TU;
601       }
602     }
603     return *NormalTypeUnits;
604   }
605 
getDWOTypeUnitMap()606   const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() {
607     if (!DWOTypeUnits) {
608       DWOTypeUnits.emplace();
609       for (const auto &U :D.dwo_units()) {
610         if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
611           (*DWOTypeUnits)[TU->getTypeHash()] = TU;
612       }
613     }
614     return *DWOTypeUnits;
615   }
616 
617   const DenseMap<uint64_t, DWARFTypeUnit *> &
getTypeUnitMap(bool IsDWO)618   getTypeUnitMap(bool IsDWO) override {
619     if (IsDWO)
620       return getDWOTypeUnitMap();
621     else
622       return getNormalTypeUnitMap();
623   }
624 };
625 
626 class ThreadSafeState : public ThreadUnsafeDWARFContextState {
627   std::recursive_mutex Mutex;
628 
629 public:
ThreadSafeState(DWARFContext & DC,std::string & DWP)630   ThreadSafeState(DWARFContext &DC, std::string &DWP) :
631       ThreadUnsafeDWARFContextState(DC, DWP) {}
632 
getNormalUnits()633   DWARFUnitVector &getNormalUnits() override {
634     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
635     return ThreadUnsafeDWARFContextState::getNormalUnits();
636   }
getDWOUnits(bool Lazy)637   DWARFUnitVector &getDWOUnits(bool Lazy) override {
638     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
639     // We need to not do lazy parsing when we need thread safety as
640     // DWARFUnitVector, in lazy mode, will slowly add things to itself and
641     // will cause problems in a multi-threaded environment.
642     return ThreadUnsafeDWARFContextState::getDWOUnits(false);
643   }
getCUIndex()644   const DWARFUnitIndex &getCUIndex() override {
645     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
646     return ThreadUnsafeDWARFContextState::getCUIndex();
647   }
getDebugAbbrevDWO()648   const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
649     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
650     return ThreadUnsafeDWARFContextState::getDebugAbbrevDWO();
651   }
652 
getTUIndex()653   const DWARFUnitIndex &getTUIndex() override {
654     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
655     return ThreadUnsafeDWARFContextState::getTUIndex();
656   }
getGdbIndex()657   DWARFGdbIndex &getGdbIndex() override {
658     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
659     return ThreadUnsafeDWARFContextState::getGdbIndex();
660   }
getDebugAbbrev()661   const DWARFDebugAbbrev *getDebugAbbrev() override {
662     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
663     return ThreadUnsafeDWARFContextState::getDebugAbbrev();
664   }
getDebugLoc()665   const DWARFDebugLoc *getDebugLoc() override {
666     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
667     return ThreadUnsafeDWARFContextState::getDebugLoc();
668   }
getDebugAranges()669   const DWARFDebugAranges *getDebugAranges() override {
670     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
671     return ThreadUnsafeDWARFContextState::getDebugAranges();
672   }
673   Expected<const DWARFDebugLine::LineTable *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)674   getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
675     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
676     return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler);
677   }
clearLineTableForUnit(DWARFUnit * U)678   void clearLineTableForUnit(DWARFUnit *U) override {
679     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
680     return ThreadUnsafeDWARFContextState::clearLineTableForUnit(U);
681   }
getDebugFrame()682   Expected<const DWARFDebugFrame *> getDebugFrame() override {
683     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
684     return ThreadUnsafeDWARFContextState::getDebugFrame();
685   }
getEHFrame()686   Expected<const DWARFDebugFrame *> getEHFrame() override {
687     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
688     return ThreadUnsafeDWARFContextState::getEHFrame();
689   }
getDebugMacinfo()690   const DWARFDebugMacro *getDebugMacinfo() override {
691     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
692     return ThreadUnsafeDWARFContextState::getDebugMacinfo();
693   }
getDebugMacinfoDWO()694   const DWARFDebugMacro *getDebugMacinfoDWO() override {
695     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
696     return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO();
697   }
getDebugMacro()698   const DWARFDebugMacro *getDebugMacro() override {
699     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
700     return ThreadUnsafeDWARFContextState::getDebugMacro();
701   }
getDebugMacroDWO()702   const DWARFDebugMacro *getDebugMacroDWO() override {
703     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
704     return ThreadUnsafeDWARFContextState::getDebugMacroDWO();
705   }
getDebugNames()706   const DWARFDebugNames &getDebugNames() override {
707     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
708     return ThreadUnsafeDWARFContextState::getDebugNames();
709   }
getAppleNames()710   const AppleAcceleratorTable &getAppleNames() override {
711     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
712     return ThreadUnsafeDWARFContextState::getAppleNames();
713   }
getAppleTypes()714   const AppleAcceleratorTable &getAppleTypes() override {
715     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
716     return ThreadUnsafeDWARFContextState::getAppleTypes();
717   }
getAppleNamespaces()718   const AppleAcceleratorTable &getAppleNamespaces() override {
719     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
720     return ThreadUnsafeDWARFContextState::getAppleNamespaces();
721   }
getAppleObjC()722   const AppleAcceleratorTable &getAppleObjC() override {
723     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
724     return ThreadUnsafeDWARFContextState::getAppleObjC();
725   }
726   std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)727   getDWOContext(StringRef AbsolutePath) override {
728     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
729     return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath);
730   }
731 
isThreadSafe() const732   bool isThreadSafe() const override { return true; }
733 
734   const DenseMap<uint64_t, DWARFTypeUnit *> &
getTypeUnitMap(bool IsDWO)735   getTypeUnitMap(bool IsDWO) override {
736     std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
737     return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO);
738   }
739 };
740 } // namespace
741 
DWARFContext(std::unique_ptr<const DWARFObject> DObj,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)742 DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
743                            std::string DWPName,
744                            std::function<void(Error)> RecoverableErrorHandler,
745                            std::function<void(Error)> WarningHandler,
746                            bool ThreadSafe)
747     : DIContext(CK_DWARF),
748       RecoverableErrorHandler(RecoverableErrorHandler),
749       WarningHandler(WarningHandler), DObj(std::move(DObj)) {
750         if (ThreadSafe)
751           State = std::make_unique<ThreadSafeState>(*this, DWPName);
752         else
753           State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);
754       }
755 
756 DWARFContext::~DWARFContext() = default;
757 
758 /// Dump the UUID load command.
dumpUUID(raw_ostream & OS,const ObjectFile & Obj)759 static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
760   auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
761   if (!MachO)
762     return;
763   for (auto LC : MachO->load_commands()) {
764     raw_ostream::uuid_t UUID;
765     if (LC.C.cmd == MachO::LC_UUID) {
766       if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
767         OS << "error: UUID load command is too short.\n";
768         return;
769       }
770       OS << "UUID: ";
771       memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
772       OS.write_uuid(UUID);
773       Triple T = MachO->getArchTriple();
774       OS << " (" << T.getArchName() << ')';
775       OS << ' ' << MachO->getFileName() << '\n';
776     }
777   }
778 }
779 
780 using ContributionCollection =
781     std::vector<std::optional<StrOffsetsContributionDescriptor>>;
782 
783 // Collect all the contributions to the string offsets table from all units,
784 // sort them by their starting offsets and remove duplicates.
785 static ContributionCollection
collectContributionData(DWARFContext::unit_iterator_range Units)786 collectContributionData(DWARFContext::unit_iterator_range Units) {
787   ContributionCollection Contributions;
788   for (const auto &U : Units)
789     if (const auto &C = U->getStringOffsetsTableContribution())
790       Contributions.push_back(C);
791   // Sort the contributions so that any invalid ones are placed at
792   // the start of the contributions vector. This way they are reported
793   // first.
794   llvm::sort(Contributions,
795              [](const std::optional<StrOffsetsContributionDescriptor> &L,
796                 const std::optional<StrOffsetsContributionDescriptor> &R) {
797                if (L && R)
798                  return L->Base < R->Base;
799                return R.has_value();
800              });
801 
802   // Uniquify contributions, as it is possible that units (specifically
803   // type units in dwo or dwp files) share contributions. We don't want
804   // to report them more than once.
805   Contributions.erase(
806       llvm::unique(
807           Contributions,
808           [](const std::optional<StrOffsetsContributionDescriptor> &L,
809              const std::optional<StrOffsetsContributionDescriptor> &R) {
810             if (L && R)
811               return L->Base == R->Base && L->Size == R->Size;
812             return false;
813           }),
814       Contributions.end());
815   return Contributions;
816 }
817 
818 // Dump a DWARF string offsets section. This may be a DWARF v5 formatted
819 // string offsets section, where each compile or type unit contributes a
820 // number of entries (string offsets), with each contribution preceded by
821 // a header containing size and version number. Alternatively, it may be a
822 // monolithic series of string offsets, as generated by the pre-DWARF v5
823 // implementation of split DWARF; however, in that case we still need to
824 // collect contributions of units because the size of the offsets (4 or 8
825 // bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).
dumpStringOffsetsSection(raw_ostream & OS,DIDumpOptions DumpOpts,StringRef SectionName,const DWARFObject & Obj,const DWARFSection & StringOffsetsSection,StringRef StringSection,DWARFContext::unit_iterator_range Units,bool LittleEndian)826 static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
827                                      StringRef SectionName,
828                                      const DWARFObject &Obj,
829                                      const DWARFSection &StringOffsetsSection,
830                                      StringRef StringSection,
831                                      DWARFContext::unit_iterator_range Units,
832                                      bool LittleEndian) {
833   auto Contributions = collectContributionData(Units);
834   DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
835   DataExtractor StrData(StringSection, LittleEndian, 0);
836   uint64_t SectionSize = StringOffsetsSection.Data.size();
837   uint64_t Offset = 0;
838   for (auto &Contribution : Contributions) {
839     // Report an ill-formed contribution.
840     if (!Contribution) {
841       OS << "error: invalid contribution to string offsets table in section ."
842          << SectionName << ".\n";
843       return;
844     }
845 
846     dwarf::DwarfFormat Format = Contribution->getFormat();
847     int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
848     uint16_t Version = Contribution->getVersion();
849     uint64_t ContributionHeader = Contribution->Base;
850     // In DWARF v5 there is a contribution header that immediately precedes
851     // the string offsets base (the location we have previously retrieved from
852     // the CU DIE's DW_AT_str_offsets attribute). The header is located either
853     // 8 or 16 bytes before the base, depending on the contribution's format.
854     if (Version >= 5)
855       ContributionHeader -= Format == DWARF32 ? 8 : 16;
856 
857     // Detect overlapping contributions.
858     if (Offset > ContributionHeader) {
859       DumpOpts.RecoverableErrorHandler(createStringError(
860           errc::invalid_argument,
861           "overlapping contributions to string offsets table in section .%s.",
862           SectionName.data()));
863     }
864     // Report a gap in the table.
865     if (Offset < ContributionHeader) {
866       OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
867       OS << (ContributionHeader - Offset) << "\n";
868     }
869     OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);
870     // In DWARF v5 the contribution size in the descriptor does not equal
871     // the originally encoded length (it does not contain the length of the
872     // version field and the padding, a total of 4 bytes). Add them back in
873     // for reporting.
874     OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
875        << ", Format = " << dwarf::FormatString(Format)
876        << ", Version = " << Version << "\n";
877 
878     Offset = Contribution->Base;
879     unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
880     while (Offset - Contribution->Base < Contribution->Size) {
881       OS << format("0x%8.8" PRIx64 ": ", Offset);
882       uint64_t StringOffset =
883           StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
884       OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);
885       const char *S = StrData.getCStr(&StringOffset);
886       if (S)
887         OS << format("\"%s\"", S);
888       OS << "\n";
889     }
890   }
891   // Report a gap at the end of the table.
892   if (Offset < SectionSize) {
893     OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
894     OS << (SectionSize - Offset) << "\n";
895   }
896 }
897 
898 // Dump the .debug_addr section.
dumpAddrSection(raw_ostream & OS,DWARFDataExtractor & AddrData,DIDumpOptions DumpOpts,uint16_t Version,uint8_t AddrSize)899 static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
900                             DIDumpOptions DumpOpts, uint16_t Version,
901                             uint8_t AddrSize) {
902   uint64_t Offset = 0;
903   while (AddrData.isValidOffset(Offset)) {
904     DWARFDebugAddrTable AddrTable;
905     uint64_t TableOffset = Offset;
906     if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
907                                       DumpOpts.WarningHandler)) {
908       DumpOpts.RecoverableErrorHandler(std::move(Err));
909       // Keep going after an error, if we can, assuming that the length field
910       // could be read. If it couldn't, stop reading the section.
911       if (auto TableLength = AddrTable.getFullLength()) {
912         Offset = TableOffset + *TableLength;
913         continue;
914       }
915       break;
916     }
917     AddrTable.dump(OS, DumpOpts);
918   }
919 }
920 
921 // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
dumpRnglistsSection(raw_ostream & OS,DWARFDataExtractor & rnglistData,llvm::function_ref<std::optional<object::SectionedAddress> (uint32_t)> LookupPooledAddress,DIDumpOptions DumpOpts)922 static void dumpRnglistsSection(
923     raw_ostream &OS, DWARFDataExtractor &rnglistData,
924     llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
925         LookupPooledAddress,
926     DIDumpOptions DumpOpts) {
927   uint64_t Offset = 0;
928   while (rnglistData.isValidOffset(Offset)) {
929     llvm::DWARFDebugRnglistTable Rnglists;
930     uint64_t TableOffset = Offset;
931     if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
932       DumpOpts.RecoverableErrorHandler(std::move(Err));
933       uint64_t Length = Rnglists.length();
934       // Keep going after an error, if we can, assuming that the length field
935       // could be read. If it couldn't, stop reading the section.
936       if (Length == 0)
937         break;
938       Offset = TableOffset + Length;
939     } else {
940       Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);
941     }
942   }
943 }
944 
945 
dumpLoclistsSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,const DWARFObject & Obj,std::optional<uint64_t> DumpOffset)946 static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
947                                 DWARFDataExtractor Data, const DWARFObject &Obj,
948                                 std::optional<uint64_t> DumpOffset) {
949   uint64_t Offset = 0;
950 
951   while (Data.isValidOffset(Offset)) {
952     DWARFListTableHeader Header(".debug_loclists", "locations");
953     if (Error E = Header.extract(Data, &Offset)) {
954       DumpOpts.RecoverableErrorHandler(std::move(E));
955       return;
956     }
957 
958     Header.dump(Data, OS, DumpOpts);
959 
960     uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
961     Data.setAddressSize(Header.getAddrSize());
962     DWARFDebugLoclists Loc(Data, Header.getVersion());
963     if (DumpOffset) {
964       if (DumpOffset >= Offset && DumpOffset < EndOffset) {
965         Offset = *DumpOffset;
966         Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
967                              nullptr, DumpOpts, /*Indent=*/0);
968         OS << "\n";
969         return;
970       }
971     } else {
972       Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
973     }
974     Offset = EndOffset;
975   }
976 }
977 
dumpPubTableSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,bool GnuStyle)978 static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,
979                                 DWARFDataExtractor Data, bool GnuStyle) {
980   DWARFDebugPubTable Table;
981   Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
982   Table.dump(OS);
983 }
984 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,std::array<std::optional<uint64_t>,DIDT_ID_Count> DumpOffsets)985 void DWARFContext::dump(
986     raw_ostream &OS, DIDumpOptions DumpOpts,
987     std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
988   uint64_t DumpType = DumpOpts.DumpType;
989 
990   StringRef Extension = sys::path::extension(DObj->getFileName());
991   bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
992 
993   // Print UUID header.
994   const auto *ObjFile = DObj->getFile();
995   if (DumpType & DIDT_UUID)
996     dumpUUID(OS, *ObjFile);
997 
998   // Print a header for each explicitly-requested section.
999   // Otherwise just print one for non-empty sections.
1000   // Only print empty .dwo section headers when dumping a .dwo file.
1001   bool Explicit = DumpType != DIDT_All && !IsDWO;
1002   bool ExplicitDWO = Explicit && IsDWO;
1003   auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
1004                         StringRef Section) -> std::optional<uint64_t> * {
1005     unsigned Mask = 1U << ID;
1006     bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
1007     if (!Should)
1008       return nullptr;
1009     OS << "\n" << Name << " contents:\n";
1010     return &DumpOffsets[ID];
1011   };
1012 
1013   // Dump individual sections.
1014   if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
1015                  DObj->getAbbrevSection()))
1016     getDebugAbbrev()->dump(OS);
1017   if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
1018                  DObj->getAbbrevDWOSection()))
1019     getDebugAbbrevDWO()->dump(OS);
1020 
1021   auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
1022     OS << '\n' << Name << " contents:\n";
1023     if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
1024       for (const auto &U : Units) {
1025         U->getDIEForOffset(*DumpOffset)
1026             .dump(OS, 0, DumpOpts.noImplicitRecursion());
1027         DWARFDie CUDie = U->getUnitDIE(false);
1028         DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false);
1029         if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {
1030           CUNonSkeletonDie.getDwarfUnit()
1031               ->getDIEForOffset(*DumpOffset)
1032               .dump(OS, 0, DumpOpts.noImplicitRecursion());
1033         }
1034       }
1035     else
1036       for (const auto &U : Units)
1037         U->dump(OS, DumpOpts);
1038   };
1039   if ((DumpType & DIDT_DebugInfo)) {
1040     if (Explicit || getNumCompileUnits())
1041       dumpDebugInfo(".debug_info", info_section_units());
1042     if (ExplicitDWO || getNumDWOCompileUnits())
1043       dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
1044   }
1045 
1046   auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
1047     OS << '\n' << Name << " contents:\n";
1048     for (const auto &U : Units)
1049       if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
1050         U->getDIEForOffset(*DumpOffset)
1051             .dump(OS, 0, DumpOpts.noImplicitRecursion());
1052       else
1053         U->dump(OS, DumpOpts);
1054   };
1055   if ((DumpType & DIDT_DebugTypes)) {
1056     if (Explicit || getNumTypeUnits())
1057       dumpDebugType(".debug_types", types_section_units());
1058     if (ExplicitDWO || getNumDWOTypeUnits())
1059       dumpDebugType(".debug_types.dwo", dwo_types_section_units());
1060   }
1061 
1062   DIDumpOptions LLDumpOpts = DumpOpts;
1063   if (LLDumpOpts.Verbose)
1064     LLDumpOpts.DisplayRawContents = true;
1065 
1066   if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
1067                                    DObj->getLocSection().Data)) {
1068     getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
1069   }
1070   if (const auto *Off =
1071           shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
1072                      DObj->getLoclistsSection().Data)) {
1073     DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
1074                             0);
1075     dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1076   }
1077   if (const auto *Off =
1078           shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
1079                      DObj->getLoclistsDWOSection().Data)) {
1080     DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
1081                             isLittleEndian(), 0);
1082     dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1083   }
1084 
1085   if (const auto *Off =
1086           shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
1087                      DObj->getLocDWOSection().Data)) {
1088     DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
1089                             4);
1090     DWARFDebugLoclists Loc(Data, /*Version=*/4);
1091     if (*Off) {
1092       uint64_t Offset = **Off;
1093       Loc.dumpLocationList(&Offset, OS,
1094                            /*BaseAddr=*/std::nullopt, *DObj, nullptr,
1095                            LLDumpOpts,
1096                            /*Indent=*/0);
1097       OS << "\n";
1098     } else {
1099       Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
1100     }
1101   }
1102 
1103   if (const std::optional<uint64_t> *Off =
1104           shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
1105                      DObj->getFrameSection().Data)) {
1106     if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
1107       (*DF)->dump(OS, DumpOpts, *Off);
1108     else
1109       RecoverableErrorHandler(DF.takeError());
1110   }
1111 
1112   if (const std::optional<uint64_t> *Off =
1113           shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
1114                      DObj->getEHFrameSection().Data)) {
1115     if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
1116       (*DF)->dump(OS, DumpOpts, *Off);
1117     else
1118       RecoverableErrorHandler(DF.takeError());
1119   }
1120 
1121   if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,
1122                  DObj->getMacroSection().Data)) {
1123     if (auto Macro = getDebugMacro())
1124       Macro->dump(OS);
1125   }
1126 
1127   if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,
1128                  DObj->getMacroDWOSection())) {
1129     if (auto MacroDWO = getDebugMacroDWO())
1130       MacroDWO->dump(OS);
1131   }
1132 
1133   if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,
1134                  DObj->getMacinfoSection())) {
1135     if (auto Macinfo = getDebugMacinfo())
1136       Macinfo->dump(OS);
1137   }
1138 
1139   if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,
1140                  DObj->getMacinfoDWOSection())) {
1141     if (auto MacinfoDWO = getDebugMacinfoDWO())
1142       MacinfoDWO->dump(OS);
1143   }
1144 
1145   if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
1146                  DObj->getArangesSection())) {
1147     uint64_t offset = 0;
1148     DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),
1149                                    0);
1150     DWARFDebugArangeSet set;
1151     while (arangesData.isValidOffset(offset)) {
1152       if (Error E =
1153               set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
1154         RecoverableErrorHandler(std::move(E));
1155         break;
1156       }
1157       set.dump(OS);
1158     }
1159   }
1160 
1161   auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
1162                              DIDumpOptions DumpOpts,
1163                              std::optional<uint64_t> DumpOffset) {
1164     while (!Parser.done()) {
1165       if (DumpOffset && Parser.getOffset() != *DumpOffset) {
1166         Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
1167         continue;
1168       }
1169       OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
1170          << "]\n";
1171       Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,
1172                        DumpOpts.Verbose);
1173     }
1174   };
1175 
1176   auto DumpStrSection = [&](StringRef Section) {
1177     DataExtractor StrData(Section, isLittleEndian(), 0);
1178     uint64_t Offset = 0;
1179     uint64_t StrOffset = 0;
1180     while (StrData.isValidOffset(Offset)) {
1181       Error Err = Error::success();
1182       const char *CStr = StrData.getCStr(&Offset, &Err);
1183       if (Err) {
1184         DumpOpts.WarningHandler(std::move(Err));
1185         return;
1186       }
1187       OS << format("0x%8.8" PRIx64 ": \"", StrOffset);
1188       OS.write_escaped(CStr);
1189       OS << "\"\n";
1190       StrOffset = Offset;
1191     }
1192   };
1193 
1194   if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
1195                                    DObj->getLineSection().Data)) {
1196     DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
1197                                 0);
1198     DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units());
1199     DumpLineSection(Parser, DumpOpts, *Off);
1200   }
1201 
1202   if (const auto *Off =
1203           shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
1204                      DObj->getLineDWOSection().Data)) {
1205     DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
1206                                 isLittleEndian(), 0);
1207     DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units());
1208     DumpLineSection(Parser, DumpOpts, *Off);
1209   }
1210 
1211   if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
1212                  DObj->getCUIndexSection())) {
1213     getCUIndex().dump(OS);
1214   }
1215 
1216   if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
1217                  DObj->getTUIndexSection())) {
1218     getTUIndex().dump(OS);
1219   }
1220 
1221   if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
1222                  DObj->getStrSection()))
1223     DumpStrSection(DObj->getStrSection());
1224 
1225   if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
1226                  DObj->getStrDWOSection()))
1227     DumpStrSection(DObj->getStrDWOSection());
1228 
1229   if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
1230                  DObj->getLineStrSection()))
1231     DumpStrSection(DObj->getLineStrSection());
1232 
1233   if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
1234                  DObj->getAddrSection().Data)) {
1235     DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
1236                                    isLittleEndian(), 0);
1237     dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
1238   }
1239 
1240   if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
1241                  DObj->getRangesSection().Data)) {
1242     uint8_t savedAddressByteSize = getCUAddrSize();
1243     DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),
1244                                   isLittleEndian(), savedAddressByteSize);
1245     uint64_t offset = 0;
1246     DWARFDebugRangeList rangeList;
1247     while (rangesData.isValidOffset(offset)) {
1248       if (Error E = rangeList.extract(rangesData, &offset)) {
1249         DumpOpts.RecoverableErrorHandler(std::move(E));
1250         break;
1251       }
1252       rangeList.dump(OS);
1253     }
1254   }
1255 
1256   auto LookupPooledAddress =
1257       [&](uint32_t Index) -> std::optional<SectionedAddress> {
1258     const auto &CUs = compile_units();
1259     auto I = CUs.begin();
1260     if (I == CUs.end())
1261       return std::nullopt;
1262     return (*I)->getAddrOffsetSectionItem(Index);
1263   };
1264 
1265   if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
1266                  DObj->getRnglistsSection().Data)) {
1267     DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
1268                                    isLittleEndian(), 0);
1269     dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1270   }
1271 
1272   if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
1273                  DObj->getRnglistsDWOSection().Data)) {
1274     DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
1275                                    isLittleEndian(), 0);
1276     dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1277   }
1278 
1279   if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
1280                  DObj->getPubnamesSection().Data)) {
1281     DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
1282                                     isLittleEndian(), 0);
1283     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1284   }
1285 
1286   if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
1287                  DObj->getPubtypesSection().Data)) {
1288     DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
1289                                     isLittleEndian(), 0);
1290     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1291   }
1292 
1293   if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
1294                  DObj->getGnuPubnamesSection().Data)) {
1295     DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
1296                                     isLittleEndian(), 0);
1297     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1298   }
1299 
1300   if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
1301                  DObj->getGnuPubtypesSection().Data)) {
1302     DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
1303                                     isLittleEndian(), 0);
1304     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1305   }
1306 
1307   if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
1308                  DObj->getStrOffsetsSection().Data))
1309     dumpStringOffsetsSection(
1310         OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
1311         DObj->getStrSection(), normal_units(), isLittleEndian());
1312   if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
1313                  DObj->getStrOffsetsDWOSection().Data))
1314     dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
1315                              DObj->getStrOffsetsDWOSection(),
1316                              DObj->getStrDWOSection(), dwo_units(),
1317                              isLittleEndian());
1318 
1319   if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
1320                  DObj->getGdbIndexSection())) {
1321     getGdbIndex().dump(OS);
1322   }
1323 
1324   if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
1325                  DObj->getAppleNamesSection().Data))
1326     getAppleNames().dump(OS);
1327 
1328   if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
1329                  DObj->getAppleTypesSection().Data))
1330     getAppleTypes().dump(OS);
1331 
1332   if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
1333                  DObj->getAppleNamespacesSection().Data))
1334     getAppleNamespaces().dump(OS);
1335 
1336   if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
1337                  DObj->getAppleObjCSection().Data))
1338     getAppleObjC().dump(OS);
1339   if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
1340                  DObj->getNamesSection().Data))
1341     getDebugNames().dump(OS);
1342 }
1343 
getTypeUnitForHash(uint64_t Hash,bool IsDWO)1344 DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint64_t Hash, bool IsDWO) {
1345   DWARFUnitVector &DWOUnits = State->getDWOUnits();
1346   if (const auto &TUI = getTUIndex()) {
1347     if (const auto *R = TUI.getFromHash(Hash))
1348       return dyn_cast_or_null<DWARFTypeUnit>(
1349           DWOUnits.getUnitForIndexEntry(*R));
1350     return nullptr;
1351   }
1352   return State->getTypeUnitMap(IsDWO).lookup(Hash);
1353 }
1354 
getDWOCompileUnitForHash(uint64_t Hash)1355 DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
1356   DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse);
1357 
1358   if (const auto &CUI = getCUIndex()) {
1359     if (const auto *R = CUI.getFromHash(Hash))
1360       return dyn_cast_or_null<DWARFCompileUnit>(
1361           DWOUnits.getUnitForIndexEntry(*R));
1362     return nullptr;
1363   }
1364 
1365   // If there's no index, just search through the CUs in the DWO - there's
1366   // probably only one unless this is something like LTO - though an in-process
1367   // built/cached lookup table could be used in that case to improve repeated
1368   // lookups of different CUs in the DWO.
1369   for (const auto &DWOCU : dwo_compile_units()) {
1370     // Might not have parsed DWO ID yet.
1371     if (!DWOCU->getDWOId()) {
1372       if (std::optional<uint64_t> DWOId =
1373               toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
1374         DWOCU->setDWOId(*DWOId);
1375       else
1376         // No DWO ID?
1377         continue;
1378     }
1379     if (DWOCU->getDWOId() == Hash)
1380       return dyn_cast<DWARFCompileUnit>(DWOCU.get());
1381   }
1382   return nullptr;
1383 }
1384 
getDIEForOffset(uint64_t Offset)1385 DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) {
1386   if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset))
1387     return CU->getDIEForOffset(Offset);
1388   return DWARFDie();
1389 }
1390 
verify(raw_ostream & OS,DIDumpOptions DumpOpts)1391 bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
1392   bool Success = true;
1393   DWARFVerifier verifier(OS, *this, DumpOpts);
1394 
1395   Success &= verifier.handleDebugAbbrev();
1396   if (DumpOpts.DumpType & DIDT_DebugCUIndex)
1397     Success &= verifier.handleDebugCUIndex();
1398   if (DumpOpts.DumpType & DIDT_DebugTUIndex)
1399     Success &= verifier.handleDebugTUIndex();
1400   if (DumpOpts.DumpType & DIDT_DebugInfo)
1401     Success &= verifier.handleDebugInfo();
1402   if (DumpOpts.DumpType & DIDT_DebugLine)
1403     Success &= verifier.handleDebugLine();
1404   if (DumpOpts.DumpType & DIDT_DebugStrOffsets)
1405     Success &= verifier.handleDebugStrOffsets();
1406   Success &= verifier.handleAccelTables();
1407   verifier.summarize();
1408   return Success;
1409 }
1410 
getCUIndex()1411 const DWARFUnitIndex &DWARFContext::getCUIndex() {
1412   return State->getCUIndex();
1413 }
1414 
getTUIndex()1415 const DWARFUnitIndex &DWARFContext::getTUIndex() {
1416   return State->getTUIndex();
1417 }
1418 
getGdbIndex()1419 DWARFGdbIndex &DWARFContext::getGdbIndex() {
1420   return State->getGdbIndex();
1421 }
1422 
getDebugAbbrev()1423 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
1424   return State->getDebugAbbrev();
1425 }
1426 
getDebugAbbrevDWO()1427 const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
1428   return State->getDebugAbbrevDWO();
1429 }
1430 
getDebugLoc()1431 const DWARFDebugLoc *DWARFContext::getDebugLoc() {
1432   return State->getDebugLoc();
1433 }
1434 
getDebugAranges()1435 const DWARFDebugAranges *DWARFContext::getDebugAranges() {
1436   return State->getDebugAranges();
1437 }
1438 
getDebugFrame()1439 Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {
1440   return State->getDebugFrame();
1441 }
1442 
getEHFrame()1443 Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {
1444   return State->getEHFrame();
1445 }
1446 
getDebugMacro()1447 const DWARFDebugMacro *DWARFContext::getDebugMacro() {
1448   return State->getDebugMacro();
1449 }
1450 
getDebugMacroDWO()1451 const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
1452   return State->getDebugMacroDWO();
1453 }
1454 
getDebugMacinfo()1455 const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {
1456   return State->getDebugMacinfo();
1457 }
1458 
getDebugMacinfoDWO()1459 const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
1460   return State->getDebugMacinfoDWO();
1461 }
1462 
1463 
getDebugNames()1464 const DWARFDebugNames &DWARFContext::getDebugNames() {
1465   return State->getDebugNames();
1466 }
1467 
getAppleNames()1468 const AppleAcceleratorTable &DWARFContext::getAppleNames() {
1469   return State->getAppleNames();
1470 }
1471 
getAppleTypes()1472 const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
1473   return State->getAppleTypes();
1474 }
1475 
getAppleNamespaces()1476 const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
1477   return State->getAppleNamespaces();
1478 }
1479 
getAppleObjC()1480 const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
1481   return State->getAppleObjC();
1482 }
1483 
1484 const DWARFDebugLine::LineTable *
getLineTableForUnit(DWARFUnit * U)1485 DWARFContext::getLineTableForUnit(DWARFUnit *U) {
1486   Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =
1487       getLineTableForUnit(U, WarningHandler);
1488   if (!ExpectedLineTable) {
1489     WarningHandler(ExpectedLineTable.takeError());
1490     return nullptr;
1491   }
1492   return *ExpectedLineTable;
1493 }
1494 
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)1495 Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
1496     DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
1497   return State->getLineTableForUnit(U, RecoverableErrorHandler);
1498 }
1499 
clearLineTableForUnit(DWARFUnit * U)1500 void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {
1501   return State->clearLineTableForUnit(U);
1502 }
1503 
getDWOUnits(bool Lazy)1504 DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
1505   return State->getDWOUnits(Lazy);
1506 }
1507 
getUnitForOffset(uint64_t Offset)1508 DWARFUnit *DWARFContext::getUnitForOffset(uint64_t Offset) {
1509   return State->getNormalUnits().getUnitForOffset(Offset);
1510 }
1511 
getCompileUnitForOffset(uint64_t Offset)1512 DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {
1513   return dyn_cast_or_null<DWARFCompileUnit>(getUnitForOffset(Offset));
1514 }
1515 
getCompileUnitForCodeAddress(uint64_t Address)1516 DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) {
1517   uint64_t CUOffset = getDebugAranges()->findAddress(Address);
1518   return getCompileUnitForOffset(CUOffset);
1519 }
1520 
getCompileUnitForDataAddress(uint64_t Address)1521 DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) {
1522   uint64_t CUOffset = getDebugAranges()->findAddress(Address);
1523   if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1524     return OffsetCU;
1525 
1526   // Global variables are often missed by the above search, for one of two
1527   // reasons:
1528   //   1. .debug_aranges may not include global variables. On clang, it seems we
1529   //      put the globals in the aranges, but this isn't true for gcc.
1530   //   2. Even if the global variable is in a .debug_arange, global variables
1531   //      may not be captured in the [start, end) addresses described by the
1532   //      parent compile unit.
1533   //
1534   // So, we walk the CU's and their child DI's manually, looking for the
1535   // specific global variable.
1536   for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1537     if (CU->getVariableForAddress(Address)) {
1538       return static_cast<DWARFCompileUnit *>(CU.get());
1539     }
1540   }
1541   return nullptr;
1542 }
1543 
getDIEsForAddress(uint64_t Address,bool CheckDWO)1544 DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address,
1545                                                              bool CheckDWO) {
1546   DIEsForAddress Result;
1547 
1548   DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address);
1549   if (!CU)
1550     return Result;
1551 
1552   if (CheckDWO) {
1553     // We were asked to check the DWO file and this debug information is more
1554     // complete that any information in the skeleton compile unit, so search the
1555     // DWO first to see if we have a match.
1556     DWARFDie CUDie = CU->getUnitDIE(false);
1557     DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false);
1558     if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) {
1559       // We have a DWO file, lets search it.
1560       DWARFCompileUnit *CUDwo =
1561           dyn_cast_or_null<DWARFCompileUnit>(CUDwoDie.getDwarfUnit());
1562       if (CUDwo) {
1563         Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address);
1564         if (Result.FunctionDIE)
1565           Result.CompileUnit = CUDwo;
1566       }
1567     }
1568   }
1569 
1570   // Search the normal DWARF if we didn't find a match in the DWO file or if
1571   // we didn't check the DWO file above.
1572   if (!Result) {
1573     Result.CompileUnit = CU;
1574     Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1575   }
1576 
1577   std::vector<DWARFDie> Worklist;
1578   Worklist.push_back(Result.FunctionDIE);
1579   while (!Worklist.empty()) {
1580     DWARFDie DIE = Worklist.back();
1581     Worklist.pop_back();
1582 
1583     if (!DIE.isValid())
1584       continue;
1585 
1586     if (DIE.getTag() == DW_TAG_lexical_block &&
1587         DIE.addressRangeContainsAddress(Address)) {
1588       Result.BlockDIE = DIE;
1589       break;
1590     }
1591 
1592     append_range(Worklist, DIE);
1593   }
1594 
1595   return Result;
1596 }
1597 
1598 /// TODO: change input parameter from "uint64_t Address"
1599 ///       into "SectionedAddress Address"
getFunctionNameAndStartLineForAddress(DWARFCompileUnit * CU,uint64_t Address,FunctionNameKind Kind,DILineInfoSpecifier::FileLineInfoKind FileNameKind,std::string & FunctionName,std::string & StartFile,uint32_t & StartLine,std::optional<uint64_t> & StartAddress)1600 static bool getFunctionNameAndStartLineForAddress(
1601     DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
1602     DILineInfoSpecifier::FileLineInfoKind FileNameKind,
1603     std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1604     std::optional<uint64_t> &StartAddress) {
1605   // The address may correspond to instruction in some inlined function,
1606   // so we have to build the chain of inlined functions and take the
1607   // name of the topmost function in it.
1608   SmallVector<DWARFDie, 4> InlinedChain;
1609   CU->getInlinedChainForAddress(Address, InlinedChain);
1610   if (InlinedChain.empty())
1611     return false;
1612 
1613   const DWARFDie &DIE = InlinedChain[0];
1614   bool FoundResult = false;
1615   const char *Name = nullptr;
1616   if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1617     FunctionName = Name;
1618     FoundResult = true;
1619   }
1620   std::string DeclFile = DIE.getDeclFile(FileNameKind);
1621   if (!DeclFile.empty()) {
1622     StartFile = DeclFile;
1623     FoundResult = true;
1624   }
1625   if (auto DeclLineResult = DIE.getDeclLine()) {
1626     StartLine = DeclLineResult;
1627     FoundResult = true;
1628   }
1629   if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1630     StartAddress = LowPcAddr->Address;
1631   return FoundResult;
1632 }
1633 
1634 static std::optional<int64_t>
getExpressionFrameOffset(ArrayRef<uint8_t> Expr,std::optional<unsigned> FrameBaseReg)1635 getExpressionFrameOffset(ArrayRef<uint8_t> Expr,
1636                          std::optional<unsigned> FrameBaseReg) {
1637   if (!Expr.empty() &&
1638       (Expr[0] == DW_OP_fbreg ||
1639        (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1640     unsigned Count;
1641     int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1642     // A single DW_OP_fbreg or DW_OP_breg.
1643     if (Expr.size() == Count + 1)
1644       return Offset;
1645     // Same + DW_OP_deref (Fortran arrays look like this).
1646     if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1647       return Offset;
1648     // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1649   }
1650   return std::nullopt;
1651 }
1652 
addLocalsForDie(DWARFCompileUnit * CU,DWARFDie Subprogram,DWARFDie Die,std::vector<DILocal> & Result)1653 void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1654                                    DWARFDie Die, std::vector<DILocal> &Result) {
1655   if (Die.getTag() == DW_TAG_variable ||
1656       Die.getTag() == DW_TAG_formal_parameter) {
1657     DILocal Local;
1658     if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1659       Local.FunctionName = Name;
1660 
1661     std::optional<unsigned> FrameBaseReg;
1662     if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1663       if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1664         if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1665             (*Expr)[0] <= DW_OP_reg31) {
1666           FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1667         }
1668 
1669     if (Expected<std::vector<DWARFLocationExpression>> Loc =
1670             Die.getLocations(DW_AT_location)) {
1671       for (const auto &Entry : *Loc) {
1672         if (std::optional<int64_t> FrameOffset =
1673                 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1674           Local.FrameOffset = *FrameOffset;
1675           break;
1676         }
1677       }
1678     } else {
1679       // FIXME: missing DW_AT_location is OK here, but other errors should be
1680       // reported to the user.
1681       consumeError(Loc.takeError());
1682     }
1683 
1684     if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1685       Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1686 
1687     if (auto Origin =
1688             Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1689       Die = Origin;
1690     if (auto NameAttr = Die.find(DW_AT_name))
1691       if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1692         Local.Name = *Name;
1693     if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1694       Local.Size = Type.getTypeSize(getCUAddrSize());
1695     if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1696       if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1697         LT->getFileNameByIndex(
1698             *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1699             DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
1700             Local.DeclFile);
1701     }
1702     if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1703       Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1704 
1705     Result.push_back(Local);
1706     return;
1707   }
1708 
1709   if (Die.getTag() == DW_TAG_inlined_subroutine)
1710     if (auto Origin =
1711             Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1712       Subprogram = Origin;
1713 
1714   for (auto Child : Die)
1715     addLocalsForDie(CU, Subprogram, Child, Result);
1716 }
1717 
1718 std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address)1719 DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
1720   std::vector<DILocal> Result;
1721   DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1722   if (!CU)
1723     return Result;
1724 
1725   DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1726   if (Subprogram.isValid())
1727     addLocalsForDie(CU, Subprogram, Subprogram, Result);
1728   return Result;
1729 }
1730 
1731 std::optional<DILineInfo>
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1732 DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
1733                                     DILineInfoSpecifier Spec) {
1734   DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1735   if (!CU)
1736     return std::nullopt;
1737 
1738   DILineInfo Result;
1739   getFunctionNameAndStartLineForAddress(
1740       CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1741       Result.StartFileName, Result.StartLine, Result.StartAddress);
1742   if (Spec.FLIKind != FileLineInfoKind::None) {
1743     if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1744       LineTable->getFileLineInfoForAddress(
1745           {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1746           CU->getCompilationDir(), Spec.FLIKind, Result);
1747     }
1748   }
1749 
1750   return Result;
1751 }
1752 
1753 std::optional<DILineInfo>
getLineInfoForDataAddress(object::SectionedAddress Address)1754 DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
1755   DILineInfo Result;
1756   DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address);
1757   if (!CU)
1758     return Result;
1759 
1760   if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1761     Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1762     Result.Line = Die.getDeclLine();
1763   }
1764 
1765   return Result;
1766 }
1767 
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Spec)1768 DILineInfoTable DWARFContext::getLineInfoForAddressRange(
1769     object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
1770   DILineInfoTable Lines;
1771   DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1772   if (!CU)
1773     return Lines;
1774 
1775   uint32_t StartLine = 0;
1776   std::string StartFileName;
1777   std::string FunctionName(DILineInfo::BadString);
1778   std::optional<uint64_t> StartAddress;
1779   getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
1780                                         Spec.FLIKind, FunctionName,
1781                                         StartFileName, StartLine, StartAddress);
1782 
1783   // If the Specifier says we don't need FileLineInfo, just
1784   // return the top-most function at the starting address.
1785   if (Spec.FLIKind == FileLineInfoKind::None) {
1786     DILineInfo Result;
1787     Result.FunctionName = FunctionName;
1788     Result.StartFileName = StartFileName;
1789     Result.StartLine = StartLine;
1790     Result.StartAddress = StartAddress;
1791     Lines.push_back(std::make_pair(Address.Address, Result));
1792     return Lines;
1793   }
1794 
1795   const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1796 
1797   // Get the index of row we're looking for in the line table.
1798   std::vector<uint32_t> RowVector;
1799   if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1800                                      Size, RowVector)) {
1801     return Lines;
1802   }
1803 
1804   for (uint32_t RowIndex : RowVector) {
1805     // Take file number and line/column from the row.
1806     const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1807     DILineInfo Result;
1808     LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1809                                   Spec.FLIKind, Result.FileName);
1810     Result.FunctionName = FunctionName;
1811     Result.Line = Row.Line;
1812     Result.Column = Row.Column;
1813     Result.StartFileName = StartFileName;
1814     Result.StartLine = StartLine;
1815     Result.StartAddress = StartAddress;
1816     Lines.push_back(std::make_pair(Row.Address.Address, Result));
1817   }
1818 
1819   return Lines;
1820 }
1821 
1822 DIInliningInfo
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1823 DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
1824                                         DILineInfoSpecifier Spec) {
1825   DIInliningInfo InliningInfo;
1826 
1827   DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1828   if (!CU)
1829     return InliningInfo;
1830 
1831   const DWARFLineTable *LineTable = nullptr;
1832   SmallVector<DWARFDie, 4> InlinedChain;
1833   CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1834   if (InlinedChain.size() == 0) {
1835     // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1836     // try to at least get file/line info from symbol table.
1837     if (Spec.FLIKind != FileLineInfoKind::None) {
1838       DILineInfo Frame;
1839       LineTable = getLineTableForUnit(CU);
1840       if (LineTable &&
1841           LineTable->getFileLineInfoForAddress(
1842               {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1843               CU->getCompilationDir(), Spec.FLIKind, Frame))
1844         InliningInfo.addFrame(Frame);
1845     }
1846     return InliningInfo;
1847   }
1848 
1849   uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
1850   for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
1851     DWARFDie &FunctionDIE = InlinedChain[i];
1852     DILineInfo Frame;
1853     // Get function name if necessary.
1854     if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
1855       Frame.FunctionName = Name;
1856     if (auto DeclLineResult = FunctionDIE.getDeclLine())
1857       Frame.StartLine = DeclLineResult;
1858     Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
1859     if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
1860       Frame.StartAddress = LowPcAddr->Address;
1861     if (Spec.FLIKind != FileLineInfoKind::None) {
1862       if (i == 0) {
1863         // For the topmost frame, initialize the line table of this
1864         // compile unit and fetch file/line info from it.
1865         LineTable = getLineTableForUnit(CU);
1866         // For the topmost routine, get file/line info from line table.
1867         if (LineTable)
1868           LineTable->getFileLineInfoForAddress(
1869               {Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
1870               CU->getCompilationDir(), Spec.FLIKind, Frame);
1871       } else {
1872         // Otherwise, use call file, call line and call column from
1873         // previous DIE in inlined chain.
1874         if (LineTable)
1875           LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
1876                                         Spec.FLIKind, Frame.FileName);
1877         Frame.Line = CallLine;
1878         Frame.Column = CallColumn;
1879         Frame.Discriminator = CallDiscriminator;
1880       }
1881       // Get call file/line/column of a current DIE.
1882       if (i + 1 < n) {
1883         FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
1884                                    CallDiscriminator);
1885       }
1886     }
1887     InliningInfo.addFrame(Frame);
1888   }
1889   return InliningInfo;
1890 }
1891 
1892 std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)1893 DWARFContext::getDWOContext(StringRef AbsolutePath) {
1894   return State->getDWOContext(AbsolutePath);
1895 }
1896 
createError(const Twine & Reason,llvm::Error E)1897 static Error createError(const Twine &Reason, llvm::Error E) {
1898   return make_error<StringError>(Reason + toString(std::move(E)),
1899                                  inconvertibleErrorCode());
1900 }
1901 
1902 /// SymInfo contains information about symbol: it's address
1903 /// and section index which is -1LL for absolute symbols.
1904 struct SymInfo {
1905   uint64_t Address = 0;
1906   uint64_t SectionIndex = 0;
1907 };
1908 
1909 /// Returns the address of symbol relocation used against and a section index.
1910 /// Used for futher relocations computation. Symbol's section load address is
getSymbolInfo(const object::ObjectFile & Obj,const RelocationRef & Reloc,const LoadedObjectInfo * L,std::map<SymbolRef,SymInfo> & Cache)1911 static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
1912                                        const RelocationRef &Reloc,
1913                                        const LoadedObjectInfo *L,
1914                                        std::map<SymbolRef, SymInfo> &Cache) {
1915   SymInfo Ret = {0, (uint64_t)-1LL};
1916   object::section_iterator RSec = Obj.section_end();
1917   object::symbol_iterator Sym = Reloc.getSymbol();
1918 
1919   std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
1920   // First calculate the address of the symbol or section as it appears
1921   // in the object file
1922   if (Sym != Obj.symbol_end()) {
1923     bool New;
1924     std::tie(CacheIt, New) = Cache.try_emplace(*Sym);
1925     if (!New)
1926       return CacheIt->second;
1927 
1928     Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
1929     if (!SymAddrOrErr)
1930       return createError("failed to compute symbol address: ",
1931                          SymAddrOrErr.takeError());
1932 
1933     // Also remember what section this symbol is in for later
1934     auto SectOrErr = Sym->getSection();
1935     if (!SectOrErr)
1936       return createError("failed to get symbol section: ",
1937                          SectOrErr.takeError());
1938 
1939     RSec = *SectOrErr;
1940     Ret.Address = *SymAddrOrErr;
1941   } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
1942     RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
1943     Ret.Address = RSec->getAddress();
1944   }
1945 
1946   if (RSec != Obj.section_end())
1947     Ret.SectionIndex = RSec->getIndex();
1948 
1949   // If we are given load addresses for the sections, we need to adjust:
1950   // SymAddr = (Address of Symbol Or Section in File) -
1951   //           (Address of Section in File) +
1952   //           (Load Address of Section)
1953   // RSec is now either the section being targeted or the section
1954   // containing the symbol being targeted. In either case,
1955   // we need to perform the same computation.
1956   if (L && RSec != Obj.section_end())
1957     if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
1958       Ret.Address += SectionLoadAddress - RSec->getAddress();
1959 
1960   if (CacheIt != Cache.end())
1961     CacheIt->second = Ret;
1962 
1963   return Ret;
1964 }
1965 
isRelocScattered(const object::ObjectFile & Obj,const RelocationRef & Reloc)1966 static bool isRelocScattered(const object::ObjectFile &Obj,
1967                              const RelocationRef &Reloc) {
1968   const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
1969   if (!MachObj)
1970     return false;
1971   // MachO also has relocations that point to sections and
1972   // scattered relocations.
1973   auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
1974   return MachObj->isRelocationScattered(RelocInfo);
1975 }
1976 
1977 namespace {
1978 struct DWARFSectionMap final : public DWARFSection {
1979   RelocAddrMap Relocs;
1980 };
1981 
1982 class DWARFObjInMemory final : public DWARFObject {
1983   bool IsLittleEndian;
1984   uint8_t AddressSize;
1985   StringRef FileName;
1986   const object::ObjectFile *Obj = nullptr;
1987   std::vector<SectionName> SectionNames;
1988 
1989   using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
1990                                    std::map<object::SectionRef, unsigned>>;
1991 
1992   InfoSectionMap InfoSections;
1993   InfoSectionMap TypesSections;
1994   InfoSectionMap InfoDWOSections;
1995   InfoSectionMap TypesDWOSections;
1996 
1997   DWARFSectionMap LocSection;
1998   DWARFSectionMap LoclistsSection;
1999   DWARFSectionMap LoclistsDWOSection;
2000   DWARFSectionMap LineSection;
2001   DWARFSectionMap RangesSection;
2002   DWARFSectionMap RnglistsSection;
2003   DWARFSectionMap StrOffsetsSection;
2004   DWARFSectionMap LineDWOSection;
2005   DWARFSectionMap FrameSection;
2006   DWARFSectionMap EHFrameSection;
2007   DWARFSectionMap LocDWOSection;
2008   DWARFSectionMap StrOffsetsDWOSection;
2009   DWARFSectionMap RangesDWOSection;
2010   DWARFSectionMap RnglistsDWOSection;
2011   DWARFSectionMap AddrSection;
2012   DWARFSectionMap AppleNamesSection;
2013   DWARFSectionMap AppleTypesSection;
2014   DWARFSectionMap AppleNamespacesSection;
2015   DWARFSectionMap AppleObjCSection;
2016   DWARFSectionMap NamesSection;
2017   DWARFSectionMap PubnamesSection;
2018   DWARFSectionMap PubtypesSection;
2019   DWARFSectionMap GnuPubnamesSection;
2020   DWARFSectionMap GnuPubtypesSection;
2021   DWARFSectionMap MacroSection;
2022 
mapNameToDWARFSection(StringRef Name)2023   DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
2024     return StringSwitch<DWARFSectionMap *>(Name)
2025         .Case("debug_loc", &LocSection)
2026         .Case("debug_loclists", &LoclistsSection)
2027         .Case("debug_loclists.dwo", &LoclistsDWOSection)
2028         .Case("debug_line", &LineSection)
2029         .Case("debug_frame", &FrameSection)
2030         .Case("eh_frame", &EHFrameSection)
2031         .Case("debug_str_offsets", &StrOffsetsSection)
2032         .Case("debug_ranges", &RangesSection)
2033         .Case("debug_rnglists", &RnglistsSection)
2034         .Case("debug_loc.dwo", &LocDWOSection)
2035         .Case("debug_line.dwo", &LineDWOSection)
2036         .Case("debug_names", &NamesSection)
2037         .Case("debug_rnglists.dwo", &RnglistsDWOSection)
2038         .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
2039         .Case("debug_addr", &AddrSection)
2040         .Case("apple_names", &AppleNamesSection)
2041         .Case("debug_pubnames", &PubnamesSection)
2042         .Case("debug_pubtypes", &PubtypesSection)
2043         .Case("debug_gnu_pubnames", &GnuPubnamesSection)
2044         .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
2045         .Case("apple_types", &AppleTypesSection)
2046         .Case("apple_namespaces", &AppleNamespacesSection)
2047         .Case("apple_namespac", &AppleNamespacesSection)
2048         .Case("apple_objc", &AppleObjCSection)
2049         .Case("debug_macro", &MacroSection)
2050         .Default(nullptr);
2051   }
2052 
2053   StringRef AbbrevSection;
2054   StringRef ArangesSection;
2055   StringRef StrSection;
2056   StringRef MacinfoSection;
2057   StringRef MacinfoDWOSection;
2058   StringRef MacroDWOSection;
2059   StringRef AbbrevDWOSection;
2060   StringRef StrDWOSection;
2061   StringRef CUIndexSection;
2062   StringRef GdbIndexSection;
2063   StringRef TUIndexSection;
2064   StringRef LineStrSection;
2065 
2066   // A deque holding section data whose iterators are not invalidated when
2067   // new decompressed sections are inserted at the end.
2068   std::deque<SmallString<0>> UncompressedSections;
2069 
mapSectionToMember(StringRef Name)2070   StringRef *mapSectionToMember(StringRef Name) {
2071     if (DWARFSection *Sec = mapNameToDWARFSection(Name))
2072       return &Sec->Data;
2073     return StringSwitch<StringRef *>(Name)
2074         .Case("debug_abbrev", &AbbrevSection)
2075         .Case("debug_aranges", &ArangesSection)
2076         .Case("debug_str", &StrSection)
2077         .Case("debug_macinfo", &MacinfoSection)
2078         .Case("debug_macinfo.dwo", &MacinfoDWOSection)
2079         .Case("debug_macro.dwo", &MacroDWOSection)
2080         .Case("debug_abbrev.dwo", &AbbrevDWOSection)
2081         .Case("debug_str.dwo", &StrDWOSection)
2082         .Case("debug_cu_index", &CUIndexSection)
2083         .Case("debug_tu_index", &TUIndexSection)
2084         .Case("gdb_index", &GdbIndexSection)
2085         .Case("debug_line_str", &LineStrSection)
2086         // Any more debug info sections go here.
2087         .Default(nullptr);
2088   }
2089 
2090   /// If Sec is compressed section, decompresses and updates its contents
2091   /// provided by Data. Otherwise leaves it unchanged.
maybeDecompress(const object::SectionRef & Sec,StringRef Name,StringRef & Data)2092   Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
2093                         StringRef &Data) {
2094     if (!Sec.isCompressed())
2095       return Error::success();
2096 
2097     Expected<Decompressor> Decompressor =
2098         Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
2099     if (!Decompressor)
2100       return Decompressor.takeError();
2101 
2102     SmallString<0> Out;
2103     if (auto Err = Decompressor->resizeAndDecompress(Out))
2104       return Err;
2105 
2106     UncompressedSections.push_back(std::move(Out));
2107     Data = UncompressedSections.back();
2108 
2109     return Error::success();
2110   }
2111 
2112 public:
DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool IsLittleEndian)2113   DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2114                    uint8_t AddrSize, bool IsLittleEndian)
2115       : IsLittleEndian(IsLittleEndian) {
2116     for (const auto &SecIt : Sections) {
2117       if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
2118         *SectionData = SecIt.second->getBuffer();
2119       else if (SecIt.first() == "debug_info")
2120         // Find debug_info and debug_types data by section rather than name as
2121         // there are multiple, comdat grouped, of these sections.
2122         InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
2123       else if (SecIt.first() == "debug_info.dwo")
2124         InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2125       else if (SecIt.first() == "debug_types")
2126         TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
2127       else if (SecIt.first() == "debug_types.dwo")
2128         TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
2129     }
2130   }
DWARFObjInMemory(const object::ObjectFile & Obj,const LoadedObjectInfo * L,function_ref<void (Error)> HandleError,function_ref<void (Error)> HandleWarning,DWARFContext::ProcessDebugRelocations RelocAction)2131   DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
2132                    function_ref<void(Error)> HandleError,
2133                    function_ref<void(Error)> HandleWarning,
2134                    DWARFContext::ProcessDebugRelocations RelocAction)
2135       : IsLittleEndian(Obj.isLittleEndian()),
2136         AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
2137         Obj(&Obj) {
2138 
2139     StringMap<unsigned> SectionAmountMap;
2140     for (const SectionRef &Section : Obj.sections()) {
2141       StringRef Name;
2142       if (auto NameOrErr = Section.getName())
2143         Name = *NameOrErr;
2144       else
2145         consumeError(NameOrErr.takeError());
2146 
2147       ++SectionAmountMap[Name];
2148       SectionNames.push_back({ Name, true });
2149 
2150       // Skip BSS and Virtual sections, they aren't interesting.
2151       if (Section.isBSS() || Section.isVirtual())
2152         continue;
2153 
2154       // Skip sections stripped by dsymutil.
2155       if (Section.isStripped())
2156         continue;
2157 
2158       StringRef Data;
2159       Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
2160       if (!SecOrErr) {
2161         HandleError(createError("failed to get relocated section: ",
2162                                 SecOrErr.takeError()));
2163         continue;
2164       }
2165 
2166       // Try to obtain an already relocated version of this section.
2167       // Else use the unrelocated section from the object file. We'll have to
2168       // apply relocations ourselves later.
2169       section_iterator RelocatedSection =
2170           Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
2171       if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
2172         Expected<StringRef> E = Section.getContents();
2173         if (E)
2174           Data = *E;
2175         else
2176           // maybeDecompress below will error.
2177           consumeError(E.takeError());
2178       }
2179 
2180       if (auto Err = maybeDecompress(Section, Name, Data)) {
2181         HandleError(createError("failed to decompress '" + Name + "', ",
2182                                 std::move(Err)));
2183         continue;
2184       }
2185 
2186       // Map platform specific debug section names to DWARF standard section
2187       // names.
2188       Name = Name.substr(Name.find_first_not_of("._"));
2189       Name = Obj.mapDebugSectionName(Name);
2190 
2191       if (StringRef *SectionData = mapSectionToMember(Name)) {
2192         *SectionData = Data;
2193         if (Name == "debug_ranges") {
2194           // FIXME: Use the other dwo range section when we emit it.
2195           RangesDWOSection.Data = Data;
2196         } else if (Name == "debug_frame" || Name == "eh_frame") {
2197           if (DWARFSection *S = mapNameToDWARFSection(Name))
2198             S->Address = Section.getAddress();
2199         }
2200       } else if (InfoSectionMap *Sections =
2201                      StringSwitch<InfoSectionMap *>(Name)
2202                          .Case("debug_info", &InfoSections)
2203                          .Case("debug_info.dwo", &InfoDWOSections)
2204                          .Case("debug_types", &TypesSections)
2205                          .Case("debug_types.dwo", &TypesDWOSections)
2206                          .Default(nullptr)) {
2207         // Find debug_info and debug_types data by section rather than name as
2208         // there are multiple, comdat grouped, of these sections.
2209         DWARFSectionMap &S = (*Sections)[Section];
2210         S.Data = Data;
2211       }
2212 
2213       if (RelocatedSection == Obj.section_end() ||
2214           (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
2215         continue;
2216 
2217       StringRef RelSecName;
2218       if (auto NameOrErr = RelocatedSection->getName())
2219         RelSecName = *NameOrErr;
2220       else
2221         consumeError(NameOrErr.takeError());
2222 
2223       // If the section we're relocating was relocated already by the JIT,
2224       // then we used the relocated version above, so we do not need to process
2225       // relocations for it now.
2226       StringRef RelSecData;
2227       if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
2228         continue;
2229 
2230       // In Mach-o files, the relocations do not need to be applied if
2231       // there is no load offset to apply. The value read at the
2232       // relocation point already factors in the section address
2233       // (actually applying the relocations will produce wrong results
2234       // as the section address will be added twice).
2235       if (!L && isa<MachOObjectFile>(&Obj))
2236         continue;
2237 
2238       if (!Section.relocations().empty() && Name.ends_with(".dwo") &&
2239           RelSecName.starts_with(".debug")) {
2240         HandleWarning(createError("unexpected relocations for dwo section '" +
2241                                   RelSecName + "'"));
2242       }
2243 
2244       // TODO: Add support for relocations in other sections as needed.
2245       // Record relocations for the debug_info and debug_line sections.
2246       RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._"));
2247       DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
2248       RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
2249       if (!Map) {
2250         // Find debug_info and debug_types relocs by section rather than name
2251         // as there are multiple, comdat grouped, of these sections.
2252         if (RelSecName == "debug_info")
2253           Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
2254                      .Relocs;
2255         else if (RelSecName == "debug_types")
2256           Map =
2257               &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
2258                    .Relocs;
2259         else
2260           continue;
2261       }
2262 
2263       if (Section.relocation_begin() == Section.relocation_end())
2264         continue;
2265 
2266       // Symbol to [address, section index] cache mapping.
2267       std::map<SymbolRef, SymInfo> AddrCache;
2268       SupportsRelocation Supports;
2269       RelocationResolver Resolver;
2270       std::tie(Supports, Resolver) = getRelocationResolver(Obj);
2271       for (const RelocationRef &Reloc : Section.relocations()) {
2272         // FIXME: it's not clear how to correctly handle scattered
2273         // relocations.
2274         if (isRelocScattered(Obj, Reloc))
2275           continue;
2276 
2277         Expected<SymInfo> SymInfoOrErr =
2278             getSymbolInfo(Obj, Reloc, L, AddrCache);
2279         if (!SymInfoOrErr) {
2280           HandleError(SymInfoOrErr.takeError());
2281           continue;
2282         }
2283 
2284         // Check if Resolver can handle this relocation type early so as not to
2285         // handle invalid cases in DWARFDataExtractor.
2286         //
2287         // TODO Don't store Resolver in every RelocAddrEntry.
2288         if (Supports && Supports(Reloc.getType())) {
2289           auto I = Map->try_emplace(
2290               Reloc.getOffset(),
2291               RelocAddrEntry{
2292                   SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
2293                   std::optional<object::RelocationRef>(), 0, Resolver});
2294           // If we didn't successfully insert that's because we already had a
2295           // relocation for that offset. Store it as a second relocation in the
2296           // same RelocAddrEntry instead.
2297           if (!I.second) {
2298             RelocAddrEntry &entry = I.first->getSecond();
2299             if (entry.Reloc2) {
2300               HandleError(createError(
2301                   "At most two relocations per offset are supported"));
2302             }
2303             entry.Reloc2 = Reloc;
2304             entry.SymbolValue2 = SymInfoOrErr->Address;
2305           }
2306         } else {
2307           SmallString<32> Type;
2308           Reloc.getTypeName(Type);
2309           // FIXME: Support more relocations & change this to an error
2310           HandleWarning(
2311               createError("failed to compute relocation: " + Type + ", ",
2312                           errorCodeToError(object_error::parse_failed)));
2313         }
2314       }
2315     }
2316 
2317     for (SectionName &S : SectionNames)
2318       if (SectionAmountMap[S.Name] > 1)
2319         S.IsNameUnique = false;
2320   }
2321 
find(const DWARFSection & S,uint64_t Pos) const2322   std::optional<RelocAddrEntry> find(const DWARFSection &S,
2323                                      uint64_t Pos) const override {
2324     auto &Sec = static_cast<const DWARFSectionMap &>(S);
2325     RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
2326     if (AI == Sec.Relocs.end())
2327       return std::nullopt;
2328     return AI->second;
2329   }
2330 
getFile() const2331   const object::ObjectFile *getFile() const override { return Obj; }
2332 
getSectionNames() const2333   ArrayRef<SectionName> getSectionNames() const override {
2334     return SectionNames;
2335   }
2336 
isLittleEndian() const2337   bool isLittleEndian() const override { return IsLittleEndian; }
getAbbrevDWOSection() const2338   StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
getLineDWOSection() const2339   const DWARFSection &getLineDWOSection() const override {
2340     return LineDWOSection;
2341   }
getLocDWOSection() const2342   const DWARFSection &getLocDWOSection() const override {
2343     return LocDWOSection;
2344   }
getStrDWOSection() const2345   StringRef getStrDWOSection() const override { return StrDWOSection; }
getStrOffsetsDWOSection() const2346   const DWARFSection &getStrOffsetsDWOSection() const override {
2347     return StrOffsetsDWOSection;
2348   }
getRangesDWOSection() const2349   const DWARFSection &getRangesDWOSection() const override {
2350     return RangesDWOSection;
2351   }
getRnglistsDWOSection() const2352   const DWARFSection &getRnglistsDWOSection() const override {
2353     return RnglistsDWOSection;
2354   }
getLoclistsDWOSection() const2355   const DWARFSection &getLoclistsDWOSection() const override {
2356     return LoclistsDWOSection;
2357   }
getAddrSection() const2358   const DWARFSection &getAddrSection() const override { return AddrSection; }
getCUIndexSection() const2359   StringRef getCUIndexSection() const override { return CUIndexSection; }
getGdbIndexSection() const2360   StringRef getGdbIndexSection() const override { return GdbIndexSection; }
getTUIndexSection() const2361   StringRef getTUIndexSection() const override { return TUIndexSection; }
2362 
2363   // DWARF v5
getStrOffsetsSection() const2364   const DWARFSection &getStrOffsetsSection() const override {
2365     return StrOffsetsSection;
2366   }
getLineStrSection() const2367   StringRef getLineStrSection() const override { return LineStrSection; }
2368 
2369   // Sections for DWARF5 split dwarf proposal.
forEachInfoDWOSections(function_ref<void (const DWARFSection &)> F) const2370   void forEachInfoDWOSections(
2371       function_ref<void(const DWARFSection &)> F) const override {
2372     for (auto &P : InfoDWOSections)
2373       F(P.second);
2374   }
forEachTypesDWOSections(function_ref<void (const DWARFSection &)> F) const2375   void forEachTypesDWOSections(
2376       function_ref<void(const DWARFSection &)> F) const override {
2377     for (auto &P : TypesDWOSections)
2378       F(P.second);
2379   }
2380 
getAbbrevSection() const2381   StringRef getAbbrevSection() const override { return AbbrevSection; }
getLocSection() const2382   const DWARFSection &getLocSection() const override { return LocSection; }
getLoclistsSection() const2383   const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
getArangesSection() const2384   StringRef getArangesSection() const override { return ArangesSection; }
getFrameSection() const2385   const DWARFSection &getFrameSection() const override {
2386     return FrameSection;
2387   }
getEHFrameSection() const2388   const DWARFSection &getEHFrameSection() const override {
2389     return EHFrameSection;
2390   }
getLineSection() const2391   const DWARFSection &getLineSection() const override { return LineSection; }
getStrSection() const2392   StringRef getStrSection() const override { return StrSection; }
getRangesSection() const2393   const DWARFSection &getRangesSection() const override { return RangesSection; }
getRnglistsSection() const2394   const DWARFSection &getRnglistsSection() const override {
2395     return RnglistsSection;
2396   }
getMacroSection() const2397   const DWARFSection &getMacroSection() const override { return MacroSection; }
getMacroDWOSection() const2398   StringRef getMacroDWOSection() const override { return MacroDWOSection; }
getMacinfoSection() const2399   StringRef getMacinfoSection() const override { return MacinfoSection; }
getMacinfoDWOSection() const2400   StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
getPubnamesSection() const2401   const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
getPubtypesSection() const2402   const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
getGnuPubnamesSection() const2403   const DWARFSection &getGnuPubnamesSection() const override {
2404     return GnuPubnamesSection;
2405   }
getGnuPubtypesSection() const2406   const DWARFSection &getGnuPubtypesSection() const override {
2407     return GnuPubtypesSection;
2408   }
getAppleNamesSection() const2409   const DWARFSection &getAppleNamesSection() const override {
2410     return AppleNamesSection;
2411   }
getAppleTypesSection() const2412   const DWARFSection &getAppleTypesSection() const override {
2413     return AppleTypesSection;
2414   }
getAppleNamespacesSection() const2415   const DWARFSection &getAppleNamespacesSection() const override {
2416     return AppleNamespacesSection;
2417   }
getAppleObjCSection() const2418   const DWARFSection &getAppleObjCSection() const override {
2419     return AppleObjCSection;
2420   }
getNamesSection() const2421   const DWARFSection &getNamesSection() const override {
2422     return NamesSection;
2423   }
2424 
getFileName() const2425   StringRef getFileName() const override { return FileName; }
getAddressSize() const2426   uint8_t getAddressSize() const override { return AddressSize; }
forEachInfoSections(function_ref<void (const DWARFSection &)> F) const2427   void forEachInfoSections(
2428       function_ref<void(const DWARFSection &)> F) const override {
2429     for (auto &P : InfoSections)
2430       F(P.second);
2431   }
forEachTypesSections(function_ref<void (const DWARFSection &)> F) const2432   void forEachTypesSections(
2433       function_ref<void(const DWARFSection &)> F) const override {
2434     for (auto &P : TypesSections)
2435       F(P.second);
2436   }
2437 };
2438 } // namespace
2439 
2440 std::unique_ptr<DWARFContext>
create(const object::ObjectFile & Obj,ProcessDebugRelocations RelocAction,const LoadedObjectInfo * L,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)2441 DWARFContext::create(const object::ObjectFile &Obj,
2442                      ProcessDebugRelocations RelocAction,
2443                      const LoadedObjectInfo *L, std::string DWPName,
2444                      std::function<void(Error)> RecoverableErrorHandler,
2445                      std::function<void(Error)> WarningHandler,
2446                      bool ThreadSafe) {
2447   auto DObj = std::make_unique<DWARFObjInMemory>(
2448       Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2449   return std::make_unique<DWARFContext>(std::move(DObj),
2450                                         std::move(DWPName),
2451                                         RecoverableErrorHandler,
2452                                         WarningHandler,
2453                                         ThreadSafe);
2454 }
2455 
2456 std::unique_ptr<DWARFContext>
create(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool isLittleEndian,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)2457 DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2458                      uint8_t AddrSize, bool isLittleEndian,
2459                      std::function<void(Error)> RecoverableErrorHandler,
2460                      std::function<void(Error)> WarningHandler,
2461                      bool ThreadSafe) {
2462   auto DObj =
2463       std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2464   return std::make_unique<DWARFContext>(
2465       std::move(DObj), "", RecoverableErrorHandler, WarningHandler, ThreadSafe);
2466 }
2467 
getCUAddrSize()2468 uint8_t DWARFContext::getCUAddrSize() {
2469   // In theory, different compile units may have different address byte
2470   // sizes, but for simplicity we just use the address byte size of the
2471   // first compile unit. In practice the address size field is repeated across
2472   // various DWARF headers (at least in version 5) to make it easier to dump
2473   // them independently, not to enable varying the address size.
2474   auto CUs = compile_units();
2475   return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
2476 }
2477 
isDWP() const2478 bool DWARFContext::isDWP() const { return !DObj->getCUIndexSection().empty(); }
2479