xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/FormatVariadic.h"
52  #include "llvm/Support/MemoryBuffer.h"
53  #include "llvm/Support/Path.h"
54  #include "llvm/Support/raw_ostream.h"
55  #include <algorithm>
56  #include <cstdint>
57  #include <deque>
58  #include <map>
59  #include <string>
60  #include <utility>
61  #include <vector>
62  
63  using namespace llvm;
64  using namespace dwarf;
65  using namespace object;
66  
67  #define DEBUG_TYPE "dwarf"
68  
69  using DWARFLineTable = DWARFDebugLine::LineTable;
70  using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
71  using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
72  
73  
fixupIndexV4(DWARFContext & C,DWARFUnitIndex & Index)74  void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index) {
75    using EntryType = DWARFUnitIndex::Entry::SectionContribution;
76    using EntryMap = DenseMap<uint32_t, EntryType>;
77    EntryMap Map;
78    const auto &DObj = C.getDWARFObj();
79    if (DObj.getCUIndexSection().empty())
80      return;
81  
82    uint64_t Offset = 0;
83    uint32_t TruncOffset = 0;
84    DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
85      if (!(C.getParseCUTUIndexManually() ||
86            S.Data.size() >= std::numeric_limits<uint32_t>::max()))
87        return;
88  
89      DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
90      while (Data.isValidOffset(Offset)) {
91        DWARFUnitHeader Header;
92        if (Error ExtractionErr = Header.extract(
93                C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
94          C.getWarningHandler()(
95              createError("Failed to parse CU header in DWP file: " +
96                          toString(std::move(ExtractionErr))));
97          Map.clear();
98          break;
99        }
100  
101        auto Iter = Map.insert({TruncOffset,
102                                {Header.getOffset(), Header.getNextUnitOffset() -
103                                                         Header.getOffset()}});
104        if (!Iter.second) {
105          logAllUnhandledErrors(
106              createError("Collision occured between for truncated offset 0x" +
107                          Twine::utohexstr(TruncOffset)),
108              errs());
109          Map.clear();
110          return;
111        }
112  
113        Offset = Header.getNextUnitOffset();
114        TruncOffset = Offset;
115      }
116    });
117  
118    if (Map.empty())
119      return;
120  
121    for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
122      if (!E.isValid())
123        continue;
124      DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
125      auto Iter = Map.find(CUOff.getOffset());
126      if (Iter == Map.end()) {
127        logAllUnhandledErrors(createError("Could not find CU offset 0x" +
128                                          Twine::utohexstr(CUOff.getOffset()) +
129                                          " in the Map"),
130                              errs());
131        break;
132      }
133      CUOff.setOffset(Iter->second.getOffset());
134      if (CUOff.getOffset() != Iter->second.getOffset())
135        logAllUnhandledErrors(createError("Length of CU in CU index doesn't "
136                                          "match calculated length at offset 0x" +
137                                          Twine::utohexstr(CUOff.getOffset())),
138                              errs());
139    }
140  }
141  
fixupIndexV5(DWARFContext & C,DWARFUnitIndex & Index)142  void fixupIndexV5(DWARFContext &C, DWARFUnitIndex &Index) {
143    DenseMap<uint64_t, uint64_t> Map;
144  
145    const auto &DObj = C.getDWARFObj();
146    DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
147      if (!(C.getParseCUTUIndexManually() ||
148            S.Data.size() >= std::numeric_limits<uint32_t>::max()))
149        return;
150      DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
151      uint64_t Offset = 0;
152      while (Data.isValidOffset(Offset)) {
153        DWARFUnitHeader Header;
154        if (Error ExtractionErr = Header.extract(
155                C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
156          C.getWarningHandler()(
157              createError("Failed to parse CU header in DWP file: " +
158                          toString(std::move(ExtractionErr))));
159          break;
160        }
161        bool CU = Header.getUnitType() == DW_UT_split_compile;
162        uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash();
163        Map[Sig] = Header.getOffset();
164        Offset = Header.getNextUnitOffset();
165      }
166    });
167    if (Map.empty())
168      return;
169    for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
170      if (!E.isValid())
171        continue;
172      DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
173      auto Iter = Map.find(E.getSignature());
174      if (Iter == Map.end()) {
175        logAllUnhandledErrors(
176            createError("Could not find unit with signature 0x" +
177                        Twine::utohexstr(E.getSignature()) + " in the Map"),
178            errs());
179        break;
180      }
181      CUOff.setOffset(Iter->second);
182    }
183  }
184  
fixupIndex(DWARFContext & C,DWARFUnitIndex & Index)185  void fixupIndex(DWARFContext &C, DWARFUnitIndex &Index) {
186    if (Index.getVersion() < 5)
187      fixupIndexV4(C, Index);
188    else
189      fixupIndexV5(C, Index);
190  }
191  
192  template <typename T>
getAccelTable(std::unique_ptr<T> & Cache,const DWARFObject & Obj,const DWARFSection & Section,StringRef StringSection,bool IsLittleEndian)193  static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
194                          const DWARFSection &Section, StringRef StringSection,
195                          bool IsLittleEndian) {
196    if (Cache)
197      return *Cache;
198    DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
199    DataExtractor StrData(StringSection, IsLittleEndian, 0);
200    Cache = std::make_unique<T>(AccelSection, StrData);
201    if (Error E = Cache->extract())
202      llvm::consumeError(std::move(E));
203    return *Cache;
204  }
205  
206  
207  std::unique_ptr<DWARFDebugMacro>
parseMacroOrMacinfo(MacroSecType SectionType)208  DWARFContext::DWARFContextState::parseMacroOrMacinfo(MacroSecType SectionType) {
209    auto Macro = std::make_unique<DWARFDebugMacro>();
210    auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {
211      if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection
212                                                      ? D.compile_units()
213                                                      : D.dwo_compile_units(),
214                                                  SectionType == MacroSection
215                                                      ? D.getStringExtractor()
216                                                      : D.getStringDWOExtractor(),
217                                                  Data)
218                              : Macro->parseMacinfo(Data)) {
219        D.getRecoverableErrorHandler()(std::move(Err));
220        Macro = nullptr;
221      }
222    };
223    const DWARFObject &DObj = D.getDWARFObj();
224    switch (SectionType) {
225    case MacinfoSection: {
226      DWARFDataExtractor Data(DObj.getMacinfoSection(), D.isLittleEndian(), 0);
227      ParseAndDump(Data, /*IsMacro=*/false);
228      break;
229    }
230    case MacinfoDwoSection: {
231      DWARFDataExtractor Data(DObj.getMacinfoDWOSection(), D.isLittleEndian(), 0);
232      ParseAndDump(Data, /*IsMacro=*/false);
233      break;
234    }
235    case MacroSection: {
236      DWARFDataExtractor Data(DObj, DObj.getMacroSection(), D.isLittleEndian(),
237                              0);
238      ParseAndDump(Data, /*IsMacro=*/true);
239      break;
240    }
241    case MacroDwoSection: {
242      DWARFDataExtractor Data(DObj.getMacroDWOSection(), D.isLittleEndian(), 0);
243      ParseAndDump(Data, /*IsMacro=*/true);
244      break;
245    }
246    }
247    return Macro;
248  }
249  
250  namespace {
251  class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {
252  
253    DWARFUnitVector NormalUnits;
254    std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits;
255    std::unique_ptr<DWARFUnitIndex> CUIndex;
256    std::unique_ptr<DWARFGdbIndex> GdbIndex;
257    std::unique_ptr<DWARFUnitIndex> TUIndex;
258    std::unique_ptr<DWARFDebugAbbrev> Abbrev;
259    std::unique_ptr<DWARFDebugLoc> Loc;
260    std::unique_ptr<DWARFDebugAranges> Aranges;
261    std::unique_ptr<DWARFDebugLine> Line;
262    std::unique_ptr<DWARFDebugFrame> DebugFrame;
263    std::unique_ptr<DWARFDebugFrame> EHFrame;
264    std::unique_ptr<DWARFDebugMacro> Macro;
265    std::unique_ptr<DWARFDebugMacro> Macinfo;
266    std::unique_ptr<DWARFDebugNames> Names;
267    std::unique_ptr<AppleAcceleratorTable> AppleNames;
268    std::unique_ptr<AppleAcceleratorTable> AppleTypes;
269    std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
270    std::unique_ptr<AppleAcceleratorTable> AppleObjC;
271    DWARFUnitVector DWOUnits;
272    std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits;
273    std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
274    std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
275    std::unique_ptr<DWARFDebugMacro> MacroDWO;
276    struct DWOFile {
277      object::OwningBinary<object::ObjectFile> File;
278      std::unique_ptr<DWARFContext> Context;
279    };
280    StringMap<std::weak_ptr<DWOFile>> DWOFiles;
281    std::weak_ptr<DWOFile> DWP;
282    bool CheckedForDWP = false;
283    std::string DWPName;
284  
285  public:
ThreadUnsafeDWARFContextState(DWARFContext & DC,std::string & DWP)286    ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :
287        DWARFContext::DWARFContextState(DC),
288        DWPName(std::move(DWP)) {}
289  
getNormalUnits()290    DWARFUnitVector &getNormalUnits() override {
291      if (NormalUnits.empty()) {
292        const DWARFObject &DObj = D.getDWARFObj();
293        DObj.forEachInfoSections([&](const DWARFSection &S) {
294          NormalUnits.addUnitsForSection(D, S, DW_SECT_INFO);
295        });
296        NormalUnits.finishedInfoUnits();
297        DObj.forEachTypesSections([&](const DWARFSection &S) {
298          NormalUnits.addUnitsForSection(D, S, DW_SECT_EXT_TYPES);
299        });
300      }
301      return NormalUnits;
302    }
303  
getDWOUnits(bool Lazy)304    DWARFUnitVector &getDWOUnits(bool Lazy) override {
305      if (DWOUnits.empty()) {
306        const DWARFObject &DObj = D.getDWARFObj();
307  
308        DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
309          DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_INFO, Lazy);
310        });
311        DWOUnits.finishedInfoUnits();
312        DObj.forEachTypesDWOSections([&](const DWARFSection &S) {
313          DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_EXT_TYPES, Lazy);
314        });
315      }
316      return DWOUnits;
317    }
318  
getDebugAbbrevDWO()319    const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
320      if (AbbrevDWO)
321        return AbbrevDWO.get();
322      const DWARFObject &DObj = D.getDWARFObj();
323      DataExtractor abbrData(DObj.getAbbrevDWOSection(), D.isLittleEndian(), 0);
324      AbbrevDWO = std::make_unique<DWARFDebugAbbrev>(abbrData);
325      return AbbrevDWO.get();
326    }
327  
getCUIndex()328    const DWARFUnitIndex &getCUIndex() override {
329      if (CUIndex)
330        return *CUIndex;
331  
332      DataExtractor Data(D.getDWARFObj().getCUIndexSection(),
333                         D.isLittleEndian(), 0);
334      CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
335      if (CUIndex->parse(Data))
336        fixupIndex(D, *CUIndex);
337      return *CUIndex;
338    }
getTUIndex()339    const DWARFUnitIndex &getTUIndex() override {
340      if (TUIndex)
341        return *TUIndex;
342  
343      DataExtractor Data(D.getDWARFObj().getTUIndexSection(),
344                         D.isLittleEndian(), 0);
345      TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
346      bool isParseSuccessful = TUIndex->parse(Data);
347      // If we are parsing TU-index and for .debug_types section we don't need
348      // to do anything.
349      if (isParseSuccessful && TUIndex->getVersion() != 2)
350        fixupIndex(D, *TUIndex);
351      return *TUIndex;
352    }
353  
getGdbIndex()354    DWARFGdbIndex &getGdbIndex() override {
355      if (GdbIndex)
356        return *GdbIndex;
357  
358      DataExtractor Data(D.getDWARFObj().getGdbIndexSection(), true /*LE*/, 0);
359      GdbIndex = std::make_unique<DWARFGdbIndex>();
360      GdbIndex->parse(Data);
361      return *GdbIndex;
362    }
363  
getDebugAbbrev()364    const DWARFDebugAbbrev *getDebugAbbrev() override {
365      if (Abbrev)
366        return Abbrev.get();
367  
368      DataExtractor Data(D.getDWARFObj().getAbbrevSection(),
369                         D.isLittleEndian(), 0);
370      Abbrev = std::make_unique<DWARFDebugAbbrev>(Data);
371      return Abbrev.get();
372    }
373  
getDebugLoc()374    const DWARFDebugLoc *getDebugLoc() override {
375      if (Loc)
376        return Loc.get();
377  
378      const DWARFObject &DObj = D.getDWARFObj();
379      // Assume all units have the same address byte size.
380      auto Data =
381          D.getNumCompileUnits()
382              ? DWARFDataExtractor(DObj, DObj.getLocSection(), D.isLittleEndian(),
383                                   D.getUnitAtIndex(0)->getAddressByteSize())
384              : DWARFDataExtractor("", D.isLittleEndian(), 0);
385      Loc = std::make_unique<DWARFDebugLoc>(std::move(Data));
386      return Loc.get();
387    }
388  
getDebugAranges()389    const DWARFDebugAranges *getDebugAranges() override {
390      if (Aranges)
391        return Aranges.get();
392  
393      Aranges = std::make_unique<DWARFDebugAranges>();
394      Aranges->generate(&D);
395      return Aranges.get();
396    }
397  
398    Expected<const DWARFDebugLine::LineTable *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)399    getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
400      if (!Line)
401        Line = std::make_unique<DWARFDebugLine>();
402  
403      auto UnitDIE = U->getUnitDIE();
404      if (!UnitDIE)
405        return nullptr;
406  
407      auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
408      if (!Offset)
409        return nullptr; // No line table for this compile unit.
410  
411      uint64_t stmtOffset = *Offset + U->getLineTableOffset();
412      // See if the line table is cached.
413      if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
414        return lt;
415  
416      // Make sure the offset is good before we try to parse.
417      if (stmtOffset >= U->getLineSection().Data.size())
418        return nullptr;
419  
420      // We have to parse it first.
421      DWARFDataExtractor Data(U->getContext().getDWARFObj(), U->getLineSection(),
422                              U->isLittleEndian(), U->getAddressByteSize());
423      return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U,
424                                       RecoverableErrorHandler);
425  
426    }
427  
clearLineTableForUnit(DWARFUnit * U)428    void clearLineTableForUnit(DWARFUnit *U) override {
429      if (!Line)
430        return;
431  
432      auto UnitDIE = U->getUnitDIE();
433      if (!UnitDIE)
434        return;
435  
436      auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
437      if (!Offset)
438        return;
439  
440      uint64_t stmtOffset = *Offset + U->getLineTableOffset();
441      Line->clearLineTable(stmtOffset);
442    }
443  
getDebugFrame()444    Expected<const DWARFDebugFrame *> getDebugFrame() override {
445      if (DebugFrame)
446        return DebugFrame.get();
447      const DWARFObject &DObj = D.getDWARFObj();
448      const DWARFSection &DS = DObj.getFrameSection();
449  
450      // There's a "bug" in the DWARFv3 standard with respect to the target address
451      // size within debug frame sections. While DWARF is supposed to be independent
452      // of its container, FDEs have fields with size being "target address size",
453      // which isn't specified in DWARF in general. It's only specified for CUs, but
454      // .eh_frame can appear without a .debug_info section. Follow the example of
455      // other tools (libdwarf) and extract this from the container (ObjectFile
456      // provides this information). This problem is fixed in DWARFv4
457      // See this dwarf-discuss discussion for more details:
458      // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
459      DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
460                              DObj.getAddressSize());
461      auto DF =
462          std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,
463                                            DS.Address);
464      if (Error E = DF->parse(Data))
465        return std::move(E);
466  
467      DebugFrame.swap(DF);
468      return DebugFrame.get();
469    }
470  
getEHFrame()471    Expected<const DWARFDebugFrame *> getEHFrame() override {
472      if (EHFrame)
473        return EHFrame.get();
474      const DWARFObject &DObj = D.getDWARFObj();
475  
476      const DWARFSection &DS = DObj.getEHFrameSection();
477      DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),
478                              DObj.getAddressSize());
479      auto DF =
480          std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,
481                                            DS.Address);
482      if (Error E = DF->parse(Data))
483        return std::move(E);
484      EHFrame.swap(DF);
485      return EHFrame.get();
486    }
487  
getDebugMacinfo()488    const DWARFDebugMacro *getDebugMacinfo() override {
489      if (!Macinfo)
490        Macinfo = parseMacroOrMacinfo(MacinfoSection);
491      return Macinfo.get();
492    }
getDebugMacinfoDWO()493    const DWARFDebugMacro *getDebugMacinfoDWO() override {
494      if (!MacinfoDWO)
495        MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
496      return MacinfoDWO.get();
497    }
getDebugMacro()498    const DWARFDebugMacro *getDebugMacro() override {
499      if (!Macro)
500        Macro = parseMacroOrMacinfo(MacroSection);
501      return Macro.get();
502    }
getDebugMacroDWO()503    const DWARFDebugMacro *getDebugMacroDWO() override {
504      if (!MacroDWO)
505        MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
506      return MacroDWO.get();
507    }
getDebugNames()508    const DWARFDebugNames &getDebugNames() override {
509      const DWARFObject &DObj = D.getDWARFObj();
510      return getAccelTable(Names, DObj, DObj.getNamesSection(),
511                           DObj.getStrSection(), D.isLittleEndian());
512    }
getAppleNames()513    const AppleAcceleratorTable &getAppleNames() override {
514      const DWARFObject &DObj = D.getDWARFObj();
515      return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(),
516                           DObj.getStrSection(), D.isLittleEndian());
517  
518    }
getAppleTypes()519    const AppleAcceleratorTable &getAppleTypes() override {
520      const DWARFObject &DObj = D.getDWARFObj();
521      return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(),
522                           DObj.getStrSection(), D.isLittleEndian());
523  
524    }
getAppleNamespaces()525    const AppleAcceleratorTable &getAppleNamespaces() override {
526      const DWARFObject &DObj = D.getDWARFObj();
527      return getAccelTable(AppleNamespaces, DObj,
528                           DObj.getAppleNamespacesSection(),
529                           DObj.getStrSection(), D.isLittleEndian());
530  
531    }
getAppleObjC()532    const AppleAcceleratorTable &getAppleObjC() override {
533      const DWARFObject &DObj = D.getDWARFObj();
534      return getAccelTable(AppleObjC, DObj, DObj.getAppleObjCSection(),
535                           DObj.getStrSection(), D.isLittleEndian());
536    }
537  
538    std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)539    getDWOContext(StringRef AbsolutePath) override {
540      if (auto S = DWP.lock()) {
541        DWARFContext *Ctxt = S->Context.get();
542        return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
543      }
544  
545      std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
546  
547      if (auto S = Entry->lock()) {
548        DWARFContext *Ctxt = S->Context.get();
549        return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
550      }
551  
552      const DWARFObject &DObj = D.getDWARFObj();
553  
554      Expected<OwningBinary<ObjectFile>> Obj = [&] {
555        if (!CheckedForDWP) {
556          SmallString<128> DWPName;
557          auto Obj = object::ObjectFile::createObjectFile(
558              this->DWPName.empty()
559                  ? (DObj.getFileName() + ".dwp").toStringRef(DWPName)
560                  : StringRef(this->DWPName));
561          if (Obj) {
562            Entry = &DWP;
563            return Obj;
564          } else {
565            CheckedForDWP = true;
566            // TODO: Should this error be handled (maybe in a high verbosity mode)
567            // before falling back to .dwo files?
568            consumeError(Obj.takeError());
569          }
570        }
571  
572        return object::ObjectFile::createObjectFile(AbsolutePath);
573      }();
574  
575      if (!Obj) {
576        // TODO: Actually report errors helpfully.
577        consumeError(Obj.takeError());
578        return nullptr;
579      }
580  
581      auto S = std::make_shared<DWOFile>();
582      S->File = std::move(Obj.get());
583      // Allow multi-threaded access if there is a .dwp file as the CU index and
584      // TU index might be accessed from multiple threads.
585      bool ThreadSafe = isThreadSafe();
586      S->Context = DWARFContext::create(
587          *S->File.getBinary(), DWARFContext::ProcessDebugRelocations::Ignore,
588          nullptr, "", WithColor::defaultErrorHandler,
589          WithColor::defaultWarningHandler, ThreadSafe);
590      *Entry = S;
591      auto *Ctxt = S->Context.get();
592      return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
593    }
594  
isThreadSafe() const595    bool isThreadSafe() const override { return false; }
596  
getNormalTypeUnitMap()597    const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() {
598      if (!NormalTypeUnits) {
599        NormalTypeUnits.emplace();
600        for (const auto &U :D.normal_units()) {
601          if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
602            (*NormalTypeUnits)[TU->getTypeHash()] = TU;
603        }
604      }
605      return *NormalTypeUnits;
606    }
607  
getDWOTypeUnitMap()608    const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() {
609      if (!DWOTypeUnits) {
610        DWOTypeUnits.emplace();
611        for (const auto &U :D.dwo_units()) {
612          if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
613            (*DWOTypeUnits)[TU->getTypeHash()] = TU;
614        }
615      }
616      return *DWOTypeUnits;
617    }
618  
619    const DenseMap<uint64_t, DWARFTypeUnit *> &
getTypeUnitMap(bool IsDWO)620    getTypeUnitMap(bool IsDWO) override {
621      if (IsDWO)
622        return getDWOTypeUnitMap();
623      else
624        return getNormalTypeUnitMap();
625    }
626  
627  
628  };
629  
630  class ThreadSafeState : public ThreadUnsafeDWARFContextState {
631    std::recursive_mutex Mutex;
632  
633  public:
ThreadSafeState(DWARFContext & DC,std::string & DWP)634    ThreadSafeState(DWARFContext &DC, std::string &DWP) :
635        ThreadUnsafeDWARFContextState(DC, DWP) {}
636  
getNormalUnits()637    DWARFUnitVector &getNormalUnits() override {
638      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
639      return ThreadUnsafeDWARFContextState::getNormalUnits();
640    }
getDWOUnits(bool Lazy)641    DWARFUnitVector &getDWOUnits(bool Lazy) override {
642      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
643      // We need to not do lazy parsing when we need thread safety as
644      // DWARFUnitVector, in lazy mode, will slowly add things to itself and
645      // will cause problems in a multi-threaded environment.
646      return ThreadUnsafeDWARFContextState::getDWOUnits(false);
647    }
getCUIndex()648    const DWARFUnitIndex &getCUIndex() override {
649      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
650      return ThreadUnsafeDWARFContextState::getCUIndex();
651    }
getDebugAbbrevDWO()652    const DWARFDebugAbbrev *getDebugAbbrevDWO() override {
653      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
654      return ThreadUnsafeDWARFContextState::getDebugAbbrevDWO();
655    }
656  
getTUIndex()657    const DWARFUnitIndex &getTUIndex() override {
658      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
659      return ThreadUnsafeDWARFContextState::getTUIndex();
660    }
getGdbIndex()661    DWARFGdbIndex &getGdbIndex() override {
662      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
663      return ThreadUnsafeDWARFContextState::getGdbIndex();
664    }
getDebugAbbrev()665    const DWARFDebugAbbrev *getDebugAbbrev() override {
666      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
667      return ThreadUnsafeDWARFContextState::getDebugAbbrev();
668    }
getDebugLoc()669    const DWARFDebugLoc *getDebugLoc() override {
670      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
671      return ThreadUnsafeDWARFContextState::getDebugLoc();
672    }
getDebugAranges()673    const DWARFDebugAranges *getDebugAranges() override {
674      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
675      return ThreadUnsafeDWARFContextState::getDebugAranges();
676    }
677    Expected<const DWARFDebugLine::LineTable *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)678    getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {
679      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
680      return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler);
681    }
clearLineTableForUnit(DWARFUnit * U)682    void clearLineTableForUnit(DWARFUnit *U) override {
683      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
684      return ThreadUnsafeDWARFContextState::clearLineTableForUnit(U);
685    }
getDebugFrame()686    Expected<const DWARFDebugFrame *> getDebugFrame() override {
687      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
688      return ThreadUnsafeDWARFContextState::getDebugFrame();
689    }
getEHFrame()690    Expected<const DWARFDebugFrame *> getEHFrame() override {
691      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
692      return ThreadUnsafeDWARFContextState::getEHFrame();
693    }
getDebugMacinfo()694    const DWARFDebugMacro *getDebugMacinfo() override {
695      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
696      return ThreadUnsafeDWARFContextState::getDebugMacinfo();
697    }
getDebugMacinfoDWO()698    const DWARFDebugMacro *getDebugMacinfoDWO() override {
699      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
700      return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO();
701    }
getDebugMacro()702    const DWARFDebugMacro *getDebugMacro() override {
703      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
704      return ThreadUnsafeDWARFContextState::getDebugMacro();
705    }
getDebugMacroDWO()706    const DWARFDebugMacro *getDebugMacroDWO() override {
707      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
708      return ThreadUnsafeDWARFContextState::getDebugMacroDWO();
709    }
getDebugNames()710    const DWARFDebugNames &getDebugNames() override {
711      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
712      return ThreadUnsafeDWARFContextState::getDebugNames();
713    }
getAppleNames()714    const AppleAcceleratorTable &getAppleNames() override {
715      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
716      return ThreadUnsafeDWARFContextState::getAppleNames();
717    }
getAppleTypes()718    const AppleAcceleratorTable &getAppleTypes() override {
719      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
720      return ThreadUnsafeDWARFContextState::getAppleTypes();
721    }
getAppleNamespaces()722    const AppleAcceleratorTable &getAppleNamespaces() override {
723      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
724      return ThreadUnsafeDWARFContextState::getAppleNamespaces();
725    }
getAppleObjC()726    const AppleAcceleratorTable &getAppleObjC() override {
727      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
728      return ThreadUnsafeDWARFContextState::getAppleObjC();
729    }
730    std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)731    getDWOContext(StringRef AbsolutePath) override {
732      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
733      return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath);
734    }
735  
isThreadSafe() const736    bool isThreadSafe() const override { return true; }
737  
738    const DenseMap<uint64_t, DWARFTypeUnit *> &
getTypeUnitMap(bool IsDWO)739    getTypeUnitMap(bool IsDWO) override {
740      std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
741      return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO);
742    }
743  };
744  } // namespace
745  
DWARFContext(std::unique_ptr<const DWARFObject> DObj,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)746  DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
747                             std::string DWPName,
748                             std::function<void(Error)> RecoverableErrorHandler,
749                             std::function<void(Error)> WarningHandler,
750                             bool ThreadSafe)
751      : DIContext(CK_DWARF),
752        RecoverableErrorHandler(RecoverableErrorHandler),
753        WarningHandler(WarningHandler), DObj(std::move(DObj)) {
754          if (ThreadSafe)
755            State = std::make_unique<ThreadSafeState>(*this, DWPName);
756          else
757            State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);
758        }
759  
760  DWARFContext::~DWARFContext() = default;
761  
762  /// Dump the UUID load command.
dumpUUID(raw_ostream & OS,const ObjectFile & Obj)763  static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
764    auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
765    if (!MachO)
766      return;
767    for (auto LC : MachO->load_commands()) {
768      raw_ostream::uuid_t UUID;
769      if (LC.C.cmd == MachO::LC_UUID) {
770        if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
771          OS << "error: UUID load command is too short.\n";
772          return;
773        }
774        OS << "UUID: ";
775        memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
776        OS.write_uuid(UUID);
777        Triple T = MachO->getArchTriple();
778        OS << " (" << T.getArchName() << ')';
779        OS << ' ' << MachO->getFileName() << '\n';
780      }
781    }
782  }
783  
784  using ContributionCollection =
785      std::vector<std::optional<StrOffsetsContributionDescriptor>>;
786  
787  // Collect all the contributions to the string offsets table from all units,
788  // sort them by their starting offsets and remove duplicates.
789  static ContributionCollection
collectContributionData(DWARFContext::unit_iterator_range Units)790  collectContributionData(DWARFContext::unit_iterator_range Units) {
791    ContributionCollection Contributions;
792    for (const auto &U : Units)
793      if (const auto &C = U->getStringOffsetsTableContribution())
794        Contributions.push_back(C);
795    // Sort the contributions so that any invalid ones are placed at
796    // the start of the contributions vector. This way they are reported
797    // first.
798    llvm::sort(Contributions,
799               [](const std::optional<StrOffsetsContributionDescriptor> &L,
800                  const std::optional<StrOffsetsContributionDescriptor> &R) {
801                 if (L && R)
802                   return L->Base < R->Base;
803                 return R.has_value();
804               });
805  
806    // Uniquify contributions, as it is possible that units (specifically
807    // type units in dwo or dwp files) share contributions. We don't want
808    // to report them more than once.
809    Contributions.erase(
810        llvm::unique(
811            Contributions,
812            [](const std::optional<StrOffsetsContributionDescriptor> &L,
813               const std::optional<StrOffsetsContributionDescriptor> &R) {
814              if (L && R)
815                return L->Base == R->Base && L->Size == R->Size;
816              return false;
817            }),
818        Contributions.end());
819    return Contributions;
820  }
821  
822  // Dump a DWARF string offsets section. This may be a DWARF v5 formatted
823  // string offsets section, where each compile or type unit contributes a
824  // number of entries (string offsets), with each contribution preceded by
825  // a header containing size and version number. Alternatively, it may be a
826  // monolithic series of string offsets, as generated by the pre-DWARF v5
827  // implementation of split DWARF; however, in that case we still need to
828  // collect contributions of units because the size of the offsets (4 or 8
829  // 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)830  static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
831                                       StringRef SectionName,
832                                       const DWARFObject &Obj,
833                                       const DWARFSection &StringOffsetsSection,
834                                       StringRef StringSection,
835                                       DWARFContext::unit_iterator_range Units,
836                                       bool LittleEndian) {
837    auto Contributions = collectContributionData(Units);
838    DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
839    DataExtractor StrData(StringSection, LittleEndian, 0);
840    uint64_t SectionSize = StringOffsetsSection.Data.size();
841    uint64_t Offset = 0;
842    for (auto &Contribution : Contributions) {
843      // Report an ill-formed contribution.
844      if (!Contribution) {
845        OS << "error: invalid contribution to string offsets table in section ."
846           << SectionName << ".\n";
847        return;
848      }
849  
850      dwarf::DwarfFormat Format = Contribution->getFormat();
851      int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
852      uint16_t Version = Contribution->getVersion();
853      uint64_t ContributionHeader = Contribution->Base;
854      // In DWARF v5 there is a contribution header that immediately precedes
855      // the string offsets base (the location we have previously retrieved from
856      // the CU DIE's DW_AT_str_offsets attribute). The header is located either
857      // 8 or 16 bytes before the base, depending on the contribution's format.
858      if (Version >= 5)
859        ContributionHeader -= Format == DWARF32 ? 8 : 16;
860  
861      // Detect overlapping contributions.
862      if (Offset > ContributionHeader) {
863        DumpOpts.RecoverableErrorHandler(createStringError(
864            errc::invalid_argument,
865            "overlapping contributions to string offsets table in section .%s.",
866            SectionName.data()));
867      }
868      // Report a gap in the table.
869      if (Offset < ContributionHeader) {
870        OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
871        OS << (ContributionHeader - Offset) << "\n";
872      }
873      OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);
874      // In DWARF v5 the contribution size in the descriptor does not equal
875      // the originally encoded length (it does not contain the length of the
876      // version field and the padding, a total of 4 bytes). Add them back in
877      // for reporting.
878      OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
879         << ", Format = " << dwarf::FormatString(Format)
880         << ", Version = " << Version << "\n";
881  
882      Offset = Contribution->Base;
883      unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
884      while (Offset - Contribution->Base < Contribution->Size) {
885        OS << format("0x%8.8" PRIx64 ": ", Offset);
886        uint64_t StringOffset =
887            StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
888        OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);
889        const char *S = StrData.getCStr(&StringOffset);
890        if (S)
891          OS << format("\"%s\"", S);
892        OS << "\n";
893      }
894    }
895    // Report a gap at the end of the table.
896    if (Offset < SectionSize) {
897      OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
898      OS << (SectionSize - Offset) << "\n";
899    }
900  }
901  
902  // Dump the .debug_addr section.
dumpAddrSection(raw_ostream & OS,DWARFDataExtractor & AddrData,DIDumpOptions DumpOpts,uint16_t Version,uint8_t AddrSize)903  static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
904                              DIDumpOptions DumpOpts, uint16_t Version,
905                              uint8_t AddrSize) {
906    uint64_t Offset = 0;
907    while (AddrData.isValidOffset(Offset)) {
908      DWARFDebugAddrTable AddrTable;
909      uint64_t TableOffset = Offset;
910      if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
911                                        DumpOpts.WarningHandler)) {
912        DumpOpts.RecoverableErrorHandler(std::move(Err));
913        // Keep going after an error, if we can, assuming that the length field
914        // could be read. If it couldn't, stop reading the section.
915        if (auto TableLength = AddrTable.getFullLength()) {
916          Offset = TableOffset + *TableLength;
917          continue;
918        }
919        break;
920      }
921      AddrTable.dump(OS, DumpOpts);
922    }
923  }
924  
925  // 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)926  static void dumpRnglistsSection(
927      raw_ostream &OS, DWARFDataExtractor &rnglistData,
928      llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
929          LookupPooledAddress,
930      DIDumpOptions DumpOpts) {
931    uint64_t Offset = 0;
932    while (rnglistData.isValidOffset(Offset)) {
933      llvm::DWARFDebugRnglistTable Rnglists;
934      uint64_t TableOffset = Offset;
935      if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
936        DumpOpts.RecoverableErrorHandler(std::move(Err));
937        uint64_t Length = Rnglists.length();
938        // Keep going after an error, if we can, assuming that the length field
939        // could be read. If it couldn't, stop reading the section.
940        if (Length == 0)
941          break;
942        Offset = TableOffset + Length;
943      } else {
944        Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);
945      }
946    }
947  }
948  
949  
dumpLoclistsSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,const DWARFObject & Obj,std::optional<uint64_t> DumpOffset)950  static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
951                                  DWARFDataExtractor Data, const DWARFObject &Obj,
952                                  std::optional<uint64_t> DumpOffset) {
953    uint64_t Offset = 0;
954  
955    while (Data.isValidOffset(Offset)) {
956      DWARFListTableHeader Header(".debug_loclists", "locations");
957      if (Error E = Header.extract(Data, &Offset)) {
958        DumpOpts.RecoverableErrorHandler(std::move(E));
959        return;
960      }
961  
962      Header.dump(Data, OS, DumpOpts);
963  
964      uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
965      Data.setAddressSize(Header.getAddrSize());
966      DWARFDebugLoclists Loc(Data, Header.getVersion());
967      if (DumpOffset) {
968        if (DumpOffset >= Offset && DumpOffset < EndOffset) {
969          Offset = *DumpOffset;
970          Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
971                               nullptr, DumpOpts, /*Indent=*/0);
972          OS << "\n";
973          return;
974        }
975      } else {
976        Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
977      }
978      Offset = EndOffset;
979    }
980  }
981  
dumpPubTableSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,bool GnuStyle)982  static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,
983                                  DWARFDataExtractor Data, bool GnuStyle) {
984    DWARFDebugPubTable Table;
985    Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
986    Table.dump(OS);
987  }
988  
dump(raw_ostream & OS,DIDumpOptions DumpOpts,std::array<std::optional<uint64_t>,DIDT_ID_Count> DumpOffsets)989  void DWARFContext::dump(
990      raw_ostream &OS, DIDumpOptions DumpOpts,
991      std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
992    uint64_t DumpType = DumpOpts.DumpType;
993  
994    StringRef Extension = sys::path::extension(DObj->getFileName());
995    bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
996  
997    // Print UUID header.
998    const auto *ObjFile = DObj->getFile();
999    if (DumpType & DIDT_UUID)
1000      dumpUUID(OS, *ObjFile);
1001  
1002    // Print a header for each explicitly-requested section.
1003    // Otherwise just print one for non-empty sections.
1004    // Only print empty .dwo section headers when dumping a .dwo file.
1005    bool Explicit = DumpType != DIDT_All && !IsDWO;
1006    bool ExplicitDWO = Explicit && IsDWO;
1007    auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
1008                          StringRef Section) -> std::optional<uint64_t> * {
1009      unsigned Mask = 1U << ID;
1010      bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
1011      if (!Should)
1012        return nullptr;
1013      OS << "\n" << Name << " contents:\n";
1014      return &DumpOffsets[ID];
1015    };
1016  
1017    // Dump individual sections.
1018    if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
1019                   DObj->getAbbrevSection()))
1020      getDebugAbbrev()->dump(OS);
1021    if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
1022                   DObj->getAbbrevDWOSection()))
1023      getDebugAbbrevDWO()->dump(OS);
1024  
1025    auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
1026      OS << '\n' << Name << " contents:\n";
1027      if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
1028        for (const auto &U : Units) {
1029          U->getDIEForOffset(*DumpOffset)
1030              .dump(OS, 0, DumpOpts.noImplicitRecursion());
1031          DWARFDie CUDie = U->getUnitDIE(false);
1032          DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false);
1033          if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {
1034            CUNonSkeletonDie.getDwarfUnit()
1035                ->getDIEForOffset(*DumpOffset)
1036                .dump(OS, 0, DumpOpts.noImplicitRecursion());
1037          }
1038        }
1039      else
1040        for (const auto &U : Units)
1041          U->dump(OS, DumpOpts);
1042    };
1043    if ((DumpType & DIDT_DebugInfo)) {
1044      if (Explicit || getNumCompileUnits())
1045        dumpDebugInfo(".debug_info", info_section_units());
1046      if (ExplicitDWO || getNumDWOCompileUnits())
1047        dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
1048    }
1049  
1050    auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
1051      OS << '\n' << Name << " contents:\n";
1052      for (const auto &U : Units)
1053        if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
1054          U->getDIEForOffset(*DumpOffset)
1055              .dump(OS, 0, DumpOpts.noImplicitRecursion());
1056        else
1057          U->dump(OS, DumpOpts);
1058    };
1059    if ((DumpType & DIDT_DebugTypes)) {
1060      if (Explicit || getNumTypeUnits())
1061        dumpDebugType(".debug_types", types_section_units());
1062      if (ExplicitDWO || getNumDWOTypeUnits())
1063        dumpDebugType(".debug_types.dwo", dwo_types_section_units());
1064    }
1065  
1066    DIDumpOptions LLDumpOpts = DumpOpts;
1067    if (LLDumpOpts.Verbose)
1068      LLDumpOpts.DisplayRawContents = true;
1069  
1070    if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
1071                                     DObj->getLocSection().Data)) {
1072      getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
1073    }
1074    if (const auto *Off =
1075            shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
1076                       DObj->getLoclistsSection().Data)) {
1077      DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
1078                              0);
1079      dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1080    }
1081    if (const auto *Off =
1082            shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
1083                       DObj->getLoclistsDWOSection().Data)) {
1084      DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
1085                              isLittleEndian(), 0);
1086      dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
1087    }
1088  
1089    if (const auto *Off =
1090            shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
1091                       DObj->getLocDWOSection().Data)) {
1092      DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
1093                              4);
1094      DWARFDebugLoclists Loc(Data, /*Version=*/4);
1095      if (*Off) {
1096        uint64_t Offset = **Off;
1097        Loc.dumpLocationList(&Offset, OS,
1098                             /*BaseAddr=*/std::nullopt, *DObj, nullptr,
1099                             LLDumpOpts,
1100                             /*Indent=*/0);
1101        OS << "\n";
1102      } else {
1103        Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
1104      }
1105    }
1106  
1107    if (const std::optional<uint64_t> *Off =
1108            shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
1109                       DObj->getFrameSection().Data)) {
1110      if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
1111        (*DF)->dump(OS, DumpOpts, *Off);
1112      else
1113        RecoverableErrorHandler(DF.takeError());
1114    }
1115  
1116    if (const std::optional<uint64_t> *Off =
1117            shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
1118                       DObj->getEHFrameSection().Data)) {
1119      if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
1120        (*DF)->dump(OS, DumpOpts, *Off);
1121      else
1122        RecoverableErrorHandler(DF.takeError());
1123    }
1124  
1125    if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,
1126                   DObj->getMacroSection().Data)) {
1127      if (auto Macro = getDebugMacro())
1128        Macro->dump(OS);
1129    }
1130  
1131    if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,
1132                   DObj->getMacroDWOSection())) {
1133      if (auto MacroDWO = getDebugMacroDWO())
1134        MacroDWO->dump(OS);
1135    }
1136  
1137    if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,
1138                   DObj->getMacinfoSection())) {
1139      if (auto Macinfo = getDebugMacinfo())
1140        Macinfo->dump(OS);
1141    }
1142  
1143    if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,
1144                   DObj->getMacinfoDWOSection())) {
1145      if (auto MacinfoDWO = getDebugMacinfoDWO())
1146        MacinfoDWO->dump(OS);
1147    }
1148  
1149    if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
1150                   DObj->getArangesSection())) {
1151      uint64_t offset = 0;
1152      DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),
1153                                     0);
1154      DWARFDebugArangeSet set;
1155      while (arangesData.isValidOffset(offset)) {
1156        if (Error E =
1157                set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
1158          RecoverableErrorHandler(std::move(E));
1159          break;
1160        }
1161        set.dump(OS);
1162      }
1163    }
1164  
1165    auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
1166                               DIDumpOptions DumpOpts,
1167                               std::optional<uint64_t> DumpOffset) {
1168      while (!Parser.done()) {
1169        if (DumpOffset && Parser.getOffset() != *DumpOffset) {
1170          Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
1171          continue;
1172        }
1173        OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
1174           << "]\n";
1175        Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,
1176                         DumpOpts.Verbose);
1177      }
1178    };
1179  
1180    auto DumpStrSection = [&](StringRef Section) {
1181      DataExtractor StrData(Section, isLittleEndian(), 0);
1182      uint64_t Offset = 0;
1183      uint64_t StrOffset = 0;
1184      while (StrData.isValidOffset(Offset)) {
1185        Error Err = Error::success();
1186        const char *CStr = StrData.getCStr(&Offset, &Err);
1187        if (Err) {
1188          DumpOpts.WarningHandler(std::move(Err));
1189          return;
1190        }
1191        OS << format("0x%8.8" PRIx64 ": \"", StrOffset);
1192        OS.write_escaped(CStr);
1193        OS << "\"\n";
1194        StrOffset = Offset;
1195      }
1196    };
1197  
1198    if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
1199                                     DObj->getLineSection().Data)) {
1200      DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
1201                                  0);
1202      DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units());
1203      DumpLineSection(Parser, DumpOpts, *Off);
1204    }
1205  
1206    if (const auto *Off =
1207            shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
1208                       DObj->getLineDWOSection().Data)) {
1209      DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
1210                                  isLittleEndian(), 0);
1211      DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units());
1212      DumpLineSection(Parser, DumpOpts, *Off);
1213    }
1214  
1215    if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
1216                   DObj->getCUIndexSection())) {
1217      getCUIndex().dump(OS);
1218    }
1219  
1220    if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
1221                   DObj->getTUIndexSection())) {
1222      getTUIndex().dump(OS);
1223    }
1224  
1225    if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
1226                   DObj->getStrSection()))
1227      DumpStrSection(DObj->getStrSection());
1228  
1229    if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
1230                   DObj->getStrDWOSection()))
1231      DumpStrSection(DObj->getStrDWOSection());
1232  
1233    if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
1234                   DObj->getLineStrSection()))
1235      DumpStrSection(DObj->getLineStrSection());
1236  
1237    if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
1238                   DObj->getAddrSection().Data)) {
1239      DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
1240                                     isLittleEndian(), 0);
1241      dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
1242    }
1243  
1244    if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
1245                   DObj->getRangesSection().Data)) {
1246      uint8_t savedAddressByteSize = getCUAddrSize();
1247      DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),
1248                                    isLittleEndian(), savedAddressByteSize);
1249      uint64_t offset = 0;
1250      DWARFDebugRangeList rangeList;
1251      while (rangesData.isValidOffset(offset)) {
1252        if (Error E = rangeList.extract(rangesData, &offset)) {
1253          DumpOpts.RecoverableErrorHandler(std::move(E));
1254          break;
1255        }
1256        rangeList.dump(OS);
1257      }
1258    }
1259  
1260    auto LookupPooledAddress =
1261        [&](uint32_t Index) -> std::optional<SectionedAddress> {
1262      const auto &CUs = compile_units();
1263      auto I = CUs.begin();
1264      if (I == CUs.end())
1265        return std::nullopt;
1266      return (*I)->getAddrOffsetSectionItem(Index);
1267    };
1268  
1269    if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
1270                   DObj->getRnglistsSection().Data)) {
1271      DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
1272                                     isLittleEndian(), 0);
1273      dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1274    }
1275  
1276    if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
1277                   DObj->getRnglistsDWOSection().Data)) {
1278      DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
1279                                     isLittleEndian(), 0);
1280      dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
1281    }
1282  
1283    if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
1284                   DObj->getPubnamesSection().Data)) {
1285      DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
1286                                      isLittleEndian(), 0);
1287      dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1288    }
1289  
1290    if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
1291                   DObj->getPubtypesSection().Data)) {
1292      DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
1293                                      isLittleEndian(), 0);
1294      dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
1295    }
1296  
1297    if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
1298                   DObj->getGnuPubnamesSection().Data)) {
1299      DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
1300                                      isLittleEndian(), 0);
1301      dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1302    }
1303  
1304    if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
1305                   DObj->getGnuPubtypesSection().Data)) {
1306      DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
1307                                      isLittleEndian(), 0);
1308      dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
1309    }
1310  
1311    if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
1312                   DObj->getStrOffsetsSection().Data))
1313      dumpStringOffsetsSection(
1314          OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
1315          DObj->getStrSection(), normal_units(), isLittleEndian());
1316    if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
1317                   DObj->getStrOffsetsDWOSection().Data))
1318      dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
1319                               DObj->getStrOffsetsDWOSection(),
1320                               DObj->getStrDWOSection(), dwo_units(),
1321                               isLittleEndian());
1322  
1323    if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
1324                   DObj->getGdbIndexSection())) {
1325      getGdbIndex().dump(OS);
1326    }
1327  
1328    if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
1329                   DObj->getAppleNamesSection().Data))
1330      getAppleNames().dump(OS);
1331  
1332    if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
1333                   DObj->getAppleTypesSection().Data))
1334      getAppleTypes().dump(OS);
1335  
1336    if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
1337                   DObj->getAppleNamespacesSection().Data))
1338      getAppleNamespaces().dump(OS);
1339  
1340    if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
1341                   DObj->getAppleObjCSection().Data))
1342      getAppleObjC().dump(OS);
1343    if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
1344                   DObj->getNamesSection().Data))
1345      getDebugNames().dump(OS);
1346  }
1347  
getTypeUnitForHash(uint16_t Version,uint64_t Hash,bool IsDWO)1348  DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,
1349                                                  bool IsDWO) {
1350    DWARFUnitVector &DWOUnits = State->getDWOUnits();
1351    if (const auto &TUI = getTUIndex()) {
1352      if (const auto *R = TUI.getFromHash(Hash))
1353        return dyn_cast_or_null<DWARFTypeUnit>(
1354            DWOUnits.getUnitForIndexEntry(*R));
1355      return nullptr;
1356    }
1357    return State->getTypeUnitMap(IsDWO).lookup(Hash);
1358  }
1359  
getDWOCompileUnitForHash(uint64_t Hash)1360  DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
1361    DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse);
1362  
1363    if (const auto &CUI = getCUIndex()) {
1364      if (const auto *R = CUI.getFromHash(Hash))
1365        return dyn_cast_or_null<DWARFCompileUnit>(
1366            DWOUnits.getUnitForIndexEntry(*R));
1367      return nullptr;
1368    }
1369  
1370    // If there's no index, just search through the CUs in the DWO - there's
1371    // probably only one unless this is something like LTO - though an in-process
1372    // built/cached lookup table could be used in that case to improve repeated
1373    // lookups of different CUs in the DWO.
1374    for (const auto &DWOCU : dwo_compile_units()) {
1375      // Might not have parsed DWO ID yet.
1376      if (!DWOCU->getDWOId()) {
1377        if (std::optional<uint64_t> DWOId =
1378                toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
1379          DWOCU->setDWOId(*DWOId);
1380        else
1381          // No DWO ID?
1382          continue;
1383      }
1384      if (DWOCU->getDWOId() == Hash)
1385        return dyn_cast<DWARFCompileUnit>(DWOCU.get());
1386    }
1387    return nullptr;
1388  }
1389  
getDIEForOffset(uint64_t Offset)1390  DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) {
1391    if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset))
1392      return CU->getDIEForOffset(Offset);
1393    return DWARFDie();
1394  }
1395  
verify(raw_ostream & OS,DIDumpOptions DumpOpts)1396  bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
1397    bool Success = true;
1398    DWARFVerifier verifier(OS, *this, DumpOpts);
1399  
1400    Success &= verifier.handleDebugAbbrev();
1401    if (DumpOpts.DumpType & DIDT_DebugCUIndex)
1402      Success &= verifier.handleDebugCUIndex();
1403    if (DumpOpts.DumpType & DIDT_DebugTUIndex)
1404      Success &= verifier.handleDebugTUIndex();
1405    if (DumpOpts.DumpType & DIDT_DebugInfo)
1406      Success &= verifier.handleDebugInfo();
1407    if (DumpOpts.DumpType & DIDT_DebugLine)
1408      Success &= verifier.handleDebugLine();
1409    if (DumpOpts.DumpType & DIDT_DebugStrOffsets)
1410      Success &= verifier.handleDebugStrOffsets();
1411    Success &= verifier.handleAccelTables();
1412    verifier.summarize();
1413    return Success;
1414  }
1415  
getCUIndex()1416  const DWARFUnitIndex &DWARFContext::getCUIndex() {
1417    return State->getCUIndex();
1418  }
1419  
getTUIndex()1420  const DWARFUnitIndex &DWARFContext::getTUIndex() {
1421    return State->getTUIndex();
1422  }
1423  
getGdbIndex()1424  DWARFGdbIndex &DWARFContext::getGdbIndex() {
1425    return State->getGdbIndex();
1426  }
1427  
getDebugAbbrev()1428  const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
1429    return State->getDebugAbbrev();
1430  }
1431  
getDebugAbbrevDWO()1432  const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
1433    return State->getDebugAbbrevDWO();
1434  }
1435  
getDebugLoc()1436  const DWARFDebugLoc *DWARFContext::getDebugLoc() {
1437    return State->getDebugLoc();
1438  }
1439  
getDebugAranges()1440  const DWARFDebugAranges *DWARFContext::getDebugAranges() {
1441    return State->getDebugAranges();
1442  }
1443  
getDebugFrame()1444  Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {
1445    return State->getDebugFrame();
1446  }
1447  
getEHFrame()1448  Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {
1449    return State->getEHFrame();
1450  }
1451  
getDebugMacro()1452  const DWARFDebugMacro *DWARFContext::getDebugMacro() {
1453    return State->getDebugMacro();
1454  }
1455  
getDebugMacroDWO()1456  const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
1457    return State->getDebugMacroDWO();
1458  }
1459  
getDebugMacinfo()1460  const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {
1461    return State->getDebugMacinfo();
1462  }
1463  
getDebugMacinfoDWO()1464  const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
1465    return State->getDebugMacinfoDWO();
1466  }
1467  
1468  
getDebugNames()1469  const DWARFDebugNames &DWARFContext::getDebugNames() {
1470    return State->getDebugNames();
1471  }
1472  
getAppleNames()1473  const AppleAcceleratorTable &DWARFContext::getAppleNames() {
1474    return State->getAppleNames();
1475  }
1476  
getAppleTypes()1477  const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
1478    return State->getAppleTypes();
1479  }
1480  
getAppleNamespaces()1481  const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
1482    return State->getAppleNamespaces();
1483  }
1484  
getAppleObjC()1485  const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
1486    return State->getAppleObjC();
1487  }
1488  
1489  const DWARFDebugLine::LineTable *
getLineTableForUnit(DWARFUnit * U)1490  DWARFContext::getLineTableForUnit(DWARFUnit *U) {
1491    Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =
1492        getLineTableForUnit(U, WarningHandler);
1493    if (!ExpectedLineTable) {
1494      WarningHandler(ExpectedLineTable.takeError());
1495      return nullptr;
1496    }
1497    return *ExpectedLineTable;
1498  }
1499  
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)1500  Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
1501      DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
1502    return State->getLineTableForUnit(U, RecoverableErrorHandler);
1503  }
1504  
clearLineTableForUnit(DWARFUnit * U)1505  void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {
1506    return State->clearLineTableForUnit(U);
1507  }
1508  
getDWOUnits(bool Lazy)1509  DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
1510    return State->getDWOUnits(Lazy);
1511  }
1512  
getCompileUnitForOffset(uint64_t Offset)1513  DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {
1514    return dyn_cast_or_null<DWARFCompileUnit>(
1515        State->getNormalUnits().getUnitForOffset(Offset));
1516  }
1517  
getCompileUnitForCodeAddress(uint64_t Address)1518  DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) {
1519    uint64_t CUOffset = getDebugAranges()->findAddress(Address);
1520    return getCompileUnitForOffset(CUOffset);
1521  }
1522  
getCompileUnitForDataAddress(uint64_t Address)1523  DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) {
1524    uint64_t CUOffset = getDebugAranges()->findAddress(Address);
1525    if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1526      return OffsetCU;
1527  
1528    // Global variables are often missed by the above search, for one of two
1529    // reasons:
1530    //   1. .debug_aranges may not include global variables. On clang, it seems we
1531    //      put the globals in the aranges, but this isn't true for gcc.
1532    //   2. Even if the global variable is in a .debug_arange, global variables
1533    //      may not be captured in the [start, end) addresses described by the
1534    //      parent compile unit.
1535    //
1536    // So, we walk the CU's and their child DI's manually, looking for the
1537    // specific global variable.
1538    for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1539      if (CU->getVariableForAddress(Address)) {
1540        return static_cast<DWARFCompileUnit *>(CU.get());
1541      }
1542    }
1543    return nullptr;
1544  }
1545  
getDIEsForAddress(uint64_t Address,bool CheckDWO)1546  DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address,
1547                                                               bool CheckDWO) {
1548    DIEsForAddress Result;
1549  
1550    DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address);
1551    if (!CU)
1552      return Result;
1553  
1554    if (CheckDWO) {
1555      // We were asked to check the DWO file and this debug information is more
1556      // complete that any information in the skeleton compile unit, so search the
1557      // DWO first to see if we have a match.
1558      DWARFDie CUDie = CU->getUnitDIE(false);
1559      DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false);
1560      if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) {
1561        // We have a DWO file, lets search it.
1562        DWARFCompileUnit *CUDwo =
1563            dyn_cast_or_null<DWARFCompileUnit>(CUDwoDie.getDwarfUnit());
1564        if (CUDwo) {
1565          Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address);
1566          if (Result.FunctionDIE)
1567            Result.CompileUnit = CUDwo;
1568        }
1569      }
1570    }
1571  
1572    // Search the normal DWARF if we didn't find a match in the DWO file or if
1573    // we didn't check the DWO file above.
1574    if (!Result) {
1575      Result.CompileUnit = CU;
1576      Result.FunctionDIE = CU->getSubroutineForAddress(Address);
1577    }
1578  
1579    std::vector<DWARFDie> Worklist;
1580    Worklist.push_back(Result.FunctionDIE);
1581    while (!Worklist.empty()) {
1582      DWARFDie DIE = Worklist.back();
1583      Worklist.pop_back();
1584  
1585      if (!DIE.isValid())
1586        continue;
1587  
1588      if (DIE.getTag() == DW_TAG_lexical_block &&
1589          DIE.addressRangeContainsAddress(Address)) {
1590        Result.BlockDIE = DIE;
1591        break;
1592      }
1593  
1594      append_range(Worklist, DIE);
1595    }
1596  
1597    return Result;
1598  }
1599  
1600  /// TODO: change input parameter from "uint64_t Address"
1601  ///       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)1602  static bool getFunctionNameAndStartLineForAddress(
1603      DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
1604      DILineInfoSpecifier::FileLineInfoKind FileNameKind,
1605      std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1606      std::optional<uint64_t> &StartAddress) {
1607    // The address may correspond to instruction in some inlined function,
1608    // so we have to build the chain of inlined functions and take the
1609    // name of the topmost function in it.
1610    SmallVector<DWARFDie, 4> InlinedChain;
1611    CU->getInlinedChainForAddress(Address, InlinedChain);
1612    if (InlinedChain.empty())
1613      return false;
1614  
1615    const DWARFDie &DIE = InlinedChain[0];
1616    bool FoundResult = false;
1617    const char *Name = nullptr;
1618    if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
1619      FunctionName = Name;
1620      FoundResult = true;
1621    }
1622    std::string DeclFile = DIE.getDeclFile(FileNameKind);
1623    if (!DeclFile.empty()) {
1624      StartFile = DeclFile;
1625      FoundResult = true;
1626    }
1627    if (auto DeclLineResult = DIE.getDeclLine()) {
1628      StartLine = DeclLineResult;
1629      FoundResult = true;
1630    }
1631    if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
1632      StartAddress = LowPcAddr->Address;
1633    return FoundResult;
1634  }
1635  
1636  static std::optional<int64_t>
getExpressionFrameOffset(ArrayRef<uint8_t> Expr,std::optional<unsigned> FrameBaseReg)1637  getExpressionFrameOffset(ArrayRef<uint8_t> Expr,
1638                           std::optional<unsigned> FrameBaseReg) {
1639    if (!Expr.empty() &&
1640        (Expr[0] == DW_OP_fbreg ||
1641         (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
1642      unsigned Count;
1643      int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
1644      // A single DW_OP_fbreg or DW_OP_breg.
1645      if (Expr.size() == Count + 1)
1646        return Offset;
1647      // Same + DW_OP_deref (Fortran arrays look like this).
1648      if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
1649        return Offset;
1650      // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
1651    }
1652    return std::nullopt;
1653  }
1654  
addLocalsForDie(DWARFCompileUnit * CU,DWARFDie Subprogram,DWARFDie Die,std::vector<DILocal> & Result)1655  void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
1656                                     DWARFDie Die, std::vector<DILocal> &Result) {
1657    if (Die.getTag() == DW_TAG_variable ||
1658        Die.getTag() == DW_TAG_formal_parameter) {
1659      DILocal Local;
1660      if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
1661        Local.FunctionName = Name;
1662  
1663      std::optional<unsigned> FrameBaseReg;
1664      if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1665        if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
1666          if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
1667              (*Expr)[0] <= DW_OP_reg31) {
1668            FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
1669          }
1670  
1671      if (Expected<std::vector<DWARFLocationExpression>> Loc =
1672              Die.getLocations(DW_AT_location)) {
1673        for (const auto &Entry : *Loc) {
1674          if (std::optional<int64_t> FrameOffset =
1675                  getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
1676            Local.FrameOffset = *FrameOffset;
1677            break;
1678          }
1679        }
1680      } else {
1681        // FIXME: missing DW_AT_location is OK here, but other errors should be
1682        // reported to the user.
1683        consumeError(Loc.takeError());
1684      }
1685  
1686      if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
1687        Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
1688  
1689      if (auto Origin =
1690              Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1691        Die = Origin;
1692      if (auto NameAttr = Die.find(DW_AT_name))
1693        if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
1694          Local.Name = *Name;
1695      if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1696        Local.Size = Type.getTypeSize(getCUAddrSize());
1697      if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
1698        if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
1699          LT->getFileNameByIndex(
1700              *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
1701              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
1702              Local.DeclFile);
1703      }
1704      if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1705        Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
1706  
1707      Result.push_back(Local);
1708      return;
1709    }
1710  
1711    if (Die.getTag() == DW_TAG_inlined_subroutine)
1712      if (auto Origin =
1713              Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
1714        Subprogram = Origin;
1715  
1716    for (auto Child : Die)
1717      addLocalsForDie(CU, Subprogram, Child, Result);
1718  }
1719  
1720  std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address)1721  DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
1722    std::vector<DILocal> Result;
1723    DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1724    if (!CU)
1725      return Result;
1726  
1727    DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
1728    if (Subprogram.isValid())
1729      addLocalsForDie(CU, Subprogram, Subprogram, Result);
1730    return Result;
1731  }
1732  
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1733  DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
1734                                                 DILineInfoSpecifier Spec) {
1735    DILineInfo Result;
1736    DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1737    if (!CU)
1738      return Result;
1739  
1740    getFunctionNameAndStartLineForAddress(
1741        CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
1742        Result.StartFileName, Result.StartLine, Result.StartAddress);
1743    if (Spec.FLIKind != FileLineInfoKind::None) {
1744      if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
1745        LineTable->getFileLineInfoForAddress(
1746            {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
1747            Spec.FLIKind, Result);
1748      }
1749    }
1750  
1751    return Result;
1752  }
1753  
1754  DILineInfo
getLineInfoForDataAddress(object::SectionedAddress Address)1755  DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
1756    DILineInfo Result;
1757    DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address);
1758    if (!CU)
1759      return Result;
1760  
1761    if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1762      Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1763      Result.Line = Die.getDeclLine();
1764    }
1765  
1766    return Result;
1767  }
1768  
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Spec)1769  DILineInfoTable DWARFContext::getLineInfoForAddressRange(
1770      object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
1771    DILineInfoTable Lines;
1772    DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1773    if (!CU)
1774      return Lines;
1775  
1776    uint32_t StartLine = 0;
1777    std::string StartFileName;
1778    std::string FunctionName(DILineInfo::BadString);
1779    std::optional<uint64_t> StartAddress;
1780    getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
1781                                          Spec.FLIKind, FunctionName,
1782                                          StartFileName, StartLine, StartAddress);
1783  
1784    // If the Specifier says we don't need FileLineInfo, just
1785    // return the top-most function at the starting address.
1786    if (Spec.FLIKind == FileLineInfoKind::None) {
1787      DILineInfo Result;
1788      Result.FunctionName = FunctionName;
1789      Result.StartFileName = StartFileName;
1790      Result.StartLine = StartLine;
1791      Result.StartAddress = StartAddress;
1792      Lines.push_back(std::make_pair(Address.Address, Result));
1793      return Lines;
1794    }
1795  
1796    const DWARFLineTable *LineTable = getLineTableForUnit(CU);
1797  
1798    // Get the index of row we're looking for in the line table.
1799    std::vector<uint32_t> RowVector;
1800    if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
1801                                       Size, RowVector)) {
1802      return Lines;
1803    }
1804  
1805    for (uint32_t RowIndex : RowVector) {
1806      // Take file number and line/column from the row.
1807      const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
1808      DILineInfo Result;
1809      LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
1810                                    Spec.FLIKind, Result.FileName);
1811      Result.FunctionName = FunctionName;
1812      Result.Line = Row.Line;
1813      Result.Column = Row.Column;
1814      Result.StartFileName = StartFileName;
1815      Result.StartLine = StartLine;
1816      Result.StartAddress = StartAddress;
1817      Lines.push_back(std::make_pair(Row.Address.Address, Result));
1818    }
1819  
1820    return Lines;
1821  }
1822  
1823  DIInliningInfo
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)1824  DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
1825                                          DILineInfoSpecifier Spec) {
1826    DIInliningInfo InliningInfo;
1827  
1828    DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);
1829    if (!CU)
1830      return InliningInfo;
1831  
1832    const DWARFLineTable *LineTable = nullptr;
1833    SmallVector<DWARFDie, 4> InlinedChain;
1834    CU->getInlinedChainForAddress(Address.Address, InlinedChain);
1835    if (InlinedChain.size() == 0) {
1836      // If there is no DIE for address (e.g. it is in unavailable .dwo file),
1837      // try to at least get file/line info from symbol table.
1838      if (Spec.FLIKind != FileLineInfoKind::None) {
1839        DILineInfo Frame;
1840        LineTable = getLineTableForUnit(CU);
1841        if (LineTable && LineTable->getFileLineInfoForAddress(
1842                             {Address.Address, Address.SectionIndex},
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}, CU->getCompilationDir(),
1870                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;
1906    uint64_t SectionIndex;
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.insert({*Sym, {0, 0}});
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