xref: /openbsd-src/gnu/llvm/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- DWARFContext.cpp ---------------------------------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h"
10*d415bd75Srobert #include "llvm/ADT/MapVector.h"
1109467b48Spatrick #include "llvm/ADT/STLExtras.h"
1209467b48Spatrick #include "llvm/ADT/SmallString.h"
1309467b48Spatrick #include "llvm/ADT/SmallVector.h"
1409467b48Spatrick #include "llvm/ADT/StringRef.h"
1509467b48Spatrick #include "llvm/ADT/StringSwitch.h"
1609467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
1709467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
1809467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
19*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
2009467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
2109467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
2209467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
2309467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
2409467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
2509467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
2609467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
2709467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
2809467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
2909467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
3009467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
3109467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFDie.h"
3209467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
3309467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
34*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFListTable.h"
35*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
36*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
3709467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFSection.h"
38*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
3909467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
4009467b48Spatrick #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
41*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
4209467b48Spatrick #include "llvm/Object/Decompressor.h"
4309467b48Spatrick #include "llvm/Object/MachO.h"
4409467b48Spatrick #include "llvm/Object/ObjectFile.h"
4509467b48Spatrick #include "llvm/Object/RelocationResolver.h"
4609467b48Spatrick #include "llvm/Support/Casting.h"
4709467b48Spatrick #include "llvm/Support/DataExtractor.h"
4809467b48Spatrick #include "llvm/Support/Error.h"
4909467b48Spatrick #include "llvm/Support/Format.h"
5009467b48Spatrick #include "llvm/Support/LEB128.h"
5109467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
5209467b48Spatrick #include "llvm/Support/Path.h"
5309467b48Spatrick #include "llvm/Support/raw_ostream.h"
5409467b48Spatrick #include <algorithm>
5509467b48Spatrick #include <cstdint>
5609467b48Spatrick #include <deque>
5709467b48Spatrick #include <map>
5809467b48Spatrick #include <string>
5909467b48Spatrick #include <utility>
6009467b48Spatrick #include <vector>
6109467b48Spatrick 
6209467b48Spatrick using namespace llvm;
6309467b48Spatrick using namespace dwarf;
6409467b48Spatrick using namespace object;
6509467b48Spatrick 
6609467b48Spatrick #define DEBUG_TYPE "dwarf"
6709467b48Spatrick 
6809467b48Spatrick using DWARFLineTable = DWARFDebugLine::LineTable;
6909467b48Spatrick using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
7009467b48Spatrick using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
7109467b48Spatrick 
DWARFContext(std::unique_ptr<const DWARFObject> DObj,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler)7209467b48Spatrick DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
73097a140dSpatrick                            std::string DWPName,
74097a140dSpatrick                            std::function<void(Error)> RecoverableErrorHandler,
75097a140dSpatrick                            std::function<void(Error)> WarningHandler)
76097a140dSpatrick     : DIContext(CK_DWARF), DWPName(std::move(DWPName)),
77097a140dSpatrick       RecoverableErrorHandler(RecoverableErrorHandler),
78097a140dSpatrick       WarningHandler(WarningHandler), DObj(std::move(DObj)) {}
7909467b48Spatrick 
8009467b48Spatrick DWARFContext::~DWARFContext() = default;
8109467b48Spatrick 
8209467b48Spatrick /// Dump the UUID load command.
dumpUUID(raw_ostream & OS,const ObjectFile & Obj)8309467b48Spatrick static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {
8409467b48Spatrick   auto *MachO = dyn_cast<MachOObjectFile>(&Obj);
8509467b48Spatrick   if (!MachO)
8609467b48Spatrick     return;
8709467b48Spatrick   for (auto LC : MachO->load_commands()) {
8809467b48Spatrick     raw_ostream::uuid_t UUID;
8909467b48Spatrick     if (LC.C.cmd == MachO::LC_UUID) {
9009467b48Spatrick       if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {
9109467b48Spatrick         OS << "error: UUID load command is too short.\n";
9209467b48Spatrick         return;
9309467b48Spatrick       }
9409467b48Spatrick       OS << "UUID: ";
9509467b48Spatrick       memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));
9609467b48Spatrick       OS.write_uuid(UUID);
9709467b48Spatrick       Triple T = MachO->getArchTriple();
9809467b48Spatrick       OS << " (" << T.getArchName() << ')';
9909467b48Spatrick       OS << ' ' << MachO->getFileName() << '\n';
10009467b48Spatrick     }
10109467b48Spatrick   }
10209467b48Spatrick }
10309467b48Spatrick 
10409467b48Spatrick using ContributionCollection =
105*d415bd75Srobert     std::vector<std::optional<StrOffsetsContributionDescriptor>>;
10609467b48Spatrick 
10709467b48Spatrick // Collect all the contributions to the string offsets table from all units,
10809467b48Spatrick // sort them by their starting offsets and remove duplicates.
10909467b48Spatrick static ContributionCollection
collectContributionData(DWARFContext::unit_iterator_range Units)11009467b48Spatrick collectContributionData(DWARFContext::unit_iterator_range Units) {
11109467b48Spatrick   ContributionCollection Contributions;
11209467b48Spatrick   for (const auto &U : Units)
11309467b48Spatrick     if (const auto &C = U->getStringOffsetsTableContribution())
11409467b48Spatrick       Contributions.push_back(C);
11509467b48Spatrick   // Sort the contributions so that any invalid ones are placed at
11609467b48Spatrick   // the start of the contributions vector. This way they are reported
11709467b48Spatrick   // first.
11809467b48Spatrick   llvm::sort(Contributions,
119*d415bd75Srobert              [](const std::optional<StrOffsetsContributionDescriptor> &L,
120*d415bd75Srobert                 const std::optional<StrOffsetsContributionDescriptor> &R) {
12109467b48Spatrick                if (L && R)
12209467b48Spatrick                  return L->Base < R->Base;
123*d415bd75Srobert                return R.has_value();
12409467b48Spatrick              });
12509467b48Spatrick 
12609467b48Spatrick   // Uniquify contributions, as it is possible that units (specifically
12709467b48Spatrick   // type units in dwo or dwp files) share contributions. We don't want
12809467b48Spatrick   // to report them more than once.
12909467b48Spatrick   Contributions.erase(
13009467b48Spatrick       std::unique(Contributions.begin(), Contributions.end(),
131*d415bd75Srobert                   [](const std::optional<StrOffsetsContributionDescriptor> &L,
132*d415bd75Srobert                      const std::optional<StrOffsetsContributionDescriptor> &R) {
13309467b48Spatrick                     if (L && R)
13409467b48Spatrick                       return L->Base == R->Base && L->Size == R->Size;
13509467b48Spatrick                     return false;
13609467b48Spatrick                   }),
13709467b48Spatrick       Contributions.end());
13809467b48Spatrick   return Contributions;
13909467b48Spatrick }
14009467b48Spatrick 
141097a140dSpatrick // Dump a DWARF string offsets section. This may be a DWARF v5 formatted
142097a140dSpatrick // string offsets section, where each compile or type unit contributes a
143097a140dSpatrick // number of entries (string offsets), with each contribution preceded by
144097a140dSpatrick // a header containing size and version number. Alternatively, it may be a
145097a140dSpatrick // monolithic series of string offsets, as generated by the pre-DWARF v5
146097a140dSpatrick // implementation of split DWARF; however, in that case we still need to
147097a140dSpatrick // collect contributions of units because the size of the offsets (4 or 8
148097a140dSpatrick // 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)149097a140dSpatrick static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
150097a140dSpatrick                                      StringRef SectionName,
151097a140dSpatrick                                      const DWARFObject &Obj,
152097a140dSpatrick                                      const DWARFSection &StringOffsetsSection,
153097a140dSpatrick                                      StringRef StringSection,
154097a140dSpatrick                                      DWARFContext::unit_iterator_range Units,
155097a140dSpatrick                                      bool LittleEndian) {
15609467b48Spatrick   auto Contributions = collectContributionData(Units);
15709467b48Spatrick   DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);
15809467b48Spatrick   DataExtractor StrData(StringSection, LittleEndian, 0);
15909467b48Spatrick   uint64_t SectionSize = StringOffsetsSection.Data.size();
16009467b48Spatrick   uint64_t Offset = 0;
16109467b48Spatrick   for (auto &Contribution : Contributions) {
16209467b48Spatrick     // Report an ill-formed contribution.
16309467b48Spatrick     if (!Contribution) {
16409467b48Spatrick       OS << "error: invalid contribution to string offsets table in section ."
16509467b48Spatrick          << SectionName << ".\n";
16609467b48Spatrick       return;
16709467b48Spatrick     }
16809467b48Spatrick 
16909467b48Spatrick     dwarf::DwarfFormat Format = Contribution->getFormat();
170097a140dSpatrick     int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
17109467b48Spatrick     uint16_t Version = Contribution->getVersion();
17209467b48Spatrick     uint64_t ContributionHeader = Contribution->Base;
17309467b48Spatrick     // In DWARF v5 there is a contribution header that immediately precedes
17409467b48Spatrick     // the string offsets base (the location we have previously retrieved from
17509467b48Spatrick     // the CU DIE's DW_AT_str_offsets attribute). The header is located either
17609467b48Spatrick     // 8 or 16 bytes before the base, depending on the contribution's format.
17709467b48Spatrick     if (Version >= 5)
17809467b48Spatrick       ContributionHeader -= Format == DWARF32 ? 8 : 16;
17909467b48Spatrick 
18009467b48Spatrick     // Detect overlapping contributions.
18109467b48Spatrick     if (Offset > ContributionHeader) {
182097a140dSpatrick       DumpOpts.RecoverableErrorHandler(createStringError(
183097a140dSpatrick           errc::invalid_argument,
184097a140dSpatrick           "overlapping contributions to string offsets table in section .%s.",
185097a140dSpatrick           SectionName.data()));
18609467b48Spatrick     }
18709467b48Spatrick     // Report a gap in the table.
18809467b48Spatrick     if (Offset < ContributionHeader) {
18909467b48Spatrick       OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
19009467b48Spatrick       OS << (ContributionHeader - Offset) << "\n";
19109467b48Spatrick     }
19209467b48Spatrick     OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);
19309467b48Spatrick     // In DWARF v5 the contribution size in the descriptor does not equal
19409467b48Spatrick     // the originally encoded length (it does not contain the length of the
19509467b48Spatrick     // version field and the padding, a total of 4 bytes). Add them back in
19609467b48Spatrick     // for reporting.
19709467b48Spatrick     OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))
198097a140dSpatrick        << ", Format = " << dwarf::FormatString(Format)
19909467b48Spatrick        << ", Version = " << Version << "\n";
20009467b48Spatrick 
20109467b48Spatrick     Offset = Contribution->Base;
20209467b48Spatrick     unsigned EntrySize = Contribution->getDwarfOffsetByteSize();
20309467b48Spatrick     while (Offset - Contribution->Base < Contribution->Size) {
20409467b48Spatrick       OS << format("0x%8.8" PRIx64 ": ", Offset);
20509467b48Spatrick       uint64_t StringOffset =
20609467b48Spatrick           StrOffsetExt.getRelocatedValue(EntrySize, &Offset);
207097a140dSpatrick       OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);
20809467b48Spatrick       const char *S = StrData.getCStr(&StringOffset);
20909467b48Spatrick       if (S)
21009467b48Spatrick         OS << format("\"%s\"", S);
21109467b48Spatrick       OS << "\n";
21209467b48Spatrick     }
21309467b48Spatrick   }
21409467b48Spatrick   // Report a gap at the end of the table.
21509467b48Spatrick   if (Offset < SectionSize) {
21609467b48Spatrick     OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);
21709467b48Spatrick     OS << (SectionSize - Offset) << "\n";
21809467b48Spatrick   }
21909467b48Spatrick }
22009467b48Spatrick 
22109467b48Spatrick // Dump the .debug_addr section.
dumpAddrSection(raw_ostream & OS,DWARFDataExtractor & AddrData,DIDumpOptions DumpOpts,uint16_t Version,uint8_t AddrSize)22209467b48Spatrick static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
22309467b48Spatrick                             DIDumpOptions DumpOpts, uint16_t Version,
22409467b48Spatrick                             uint8_t AddrSize) {
22509467b48Spatrick   uint64_t Offset = 0;
22609467b48Spatrick   while (AddrData.isValidOffset(Offset)) {
22709467b48Spatrick     DWARFDebugAddrTable AddrTable;
22809467b48Spatrick     uint64_t TableOffset = Offset;
22909467b48Spatrick     if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,
230097a140dSpatrick                                       DumpOpts.WarningHandler)) {
231097a140dSpatrick       DumpOpts.RecoverableErrorHandler(std::move(Err));
23209467b48Spatrick       // Keep going after an error, if we can, assuming that the length field
23309467b48Spatrick       // could be read. If it couldn't, stop reading the section.
234097a140dSpatrick       if (auto TableLength = AddrTable.getFullLength()) {
235097a140dSpatrick         Offset = TableOffset + *TableLength;
236097a140dSpatrick         continue;
23709467b48Spatrick       }
238097a140dSpatrick       break;
239097a140dSpatrick     }
240097a140dSpatrick     AddrTable.dump(OS, DumpOpts);
24109467b48Spatrick   }
24209467b48Spatrick }
24309467b48Spatrick 
24409467b48Spatrick // 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)24509467b48Spatrick static void dumpRnglistsSection(
24609467b48Spatrick     raw_ostream &OS, DWARFDataExtractor &rnglistData,
247*d415bd75Srobert     llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>
24809467b48Spatrick         LookupPooledAddress,
24909467b48Spatrick     DIDumpOptions DumpOpts) {
25009467b48Spatrick   uint64_t Offset = 0;
25109467b48Spatrick   while (rnglistData.isValidOffset(Offset)) {
25209467b48Spatrick     llvm::DWARFDebugRnglistTable Rnglists;
25309467b48Spatrick     uint64_t TableOffset = Offset;
25409467b48Spatrick     if (Error Err = Rnglists.extract(rnglistData, &Offset)) {
255097a140dSpatrick       DumpOpts.RecoverableErrorHandler(std::move(Err));
25609467b48Spatrick       uint64_t Length = Rnglists.length();
25709467b48Spatrick       // Keep going after an error, if we can, assuming that the length field
25809467b48Spatrick       // could be read. If it couldn't, stop reading the section.
25909467b48Spatrick       if (Length == 0)
26009467b48Spatrick         break;
26109467b48Spatrick       Offset = TableOffset + Length;
26209467b48Spatrick     } else {
26373471bf0Spatrick       Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);
26409467b48Spatrick     }
26509467b48Spatrick   }
26609467b48Spatrick }
26709467b48Spatrick 
268097a140dSpatrick std::unique_ptr<DWARFDebugMacro>
parseMacroOrMacinfo(MacroSecType SectionType)269097a140dSpatrick DWARFContext::parseMacroOrMacinfo(MacroSecType SectionType) {
270097a140dSpatrick   auto Macro = std::make_unique<DWARFDebugMacro>();
271097a140dSpatrick   auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {
272097a140dSpatrick     if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection
273097a140dSpatrick                                                     ? compile_units()
274097a140dSpatrick                                                     : dwo_compile_units(),
275097a140dSpatrick                                                 SectionType == MacroSection
276097a140dSpatrick                                                     ? getStringExtractor()
277097a140dSpatrick                                                     : getStringDWOExtractor(),
278097a140dSpatrick                                                 Data)
279097a140dSpatrick                             : Macro->parseMacinfo(Data)) {
280097a140dSpatrick       RecoverableErrorHandler(std::move(Err));
281097a140dSpatrick       Macro = nullptr;
282097a140dSpatrick     }
283097a140dSpatrick   };
284097a140dSpatrick   switch (SectionType) {
285097a140dSpatrick   case MacinfoSection: {
286097a140dSpatrick     DWARFDataExtractor Data(DObj->getMacinfoSection(), isLittleEndian(), 0);
287097a140dSpatrick     ParseAndDump(Data, /*IsMacro=*/false);
288097a140dSpatrick     break;
289097a140dSpatrick   }
290097a140dSpatrick   case MacinfoDwoSection: {
291097a140dSpatrick     DWARFDataExtractor Data(DObj->getMacinfoDWOSection(), isLittleEndian(), 0);
292097a140dSpatrick     ParseAndDump(Data, /*IsMacro=*/false);
293097a140dSpatrick     break;
294097a140dSpatrick   }
295097a140dSpatrick   case MacroSection: {
296097a140dSpatrick     DWARFDataExtractor Data(*DObj, DObj->getMacroSection(), isLittleEndian(),
297097a140dSpatrick                             0);
298097a140dSpatrick     ParseAndDump(Data, /*IsMacro=*/true);
299097a140dSpatrick     break;
300097a140dSpatrick   }
301097a140dSpatrick   case MacroDwoSection: {
302097a140dSpatrick     DWARFDataExtractor Data(DObj->getMacroDWOSection(), isLittleEndian(), 0);
303097a140dSpatrick     ParseAndDump(Data, /*IsMacro=*/true);
304097a140dSpatrick     break;
305097a140dSpatrick   }
306097a140dSpatrick   }
307097a140dSpatrick   return Macro;
308097a140dSpatrick }
309097a140dSpatrick 
dumpLoclistsSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,const DWARFObject & Obj,std::optional<uint64_t> DumpOffset)31009467b48Spatrick static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
311*d415bd75Srobert                                 DWARFDataExtractor Data, const DWARFObject &Obj,
312*d415bd75Srobert                                 std::optional<uint64_t> DumpOffset) {
31309467b48Spatrick   uint64_t Offset = 0;
31409467b48Spatrick 
31509467b48Spatrick   while (Data.isValidOffset(Offset)) {
31609467b48Spatrick     DWARFListTableHeader Header(".debug_loclists", "locations");
31709467b48Spatrick     if (Error E = Header.extract(Data, &Offset)) {
318097a140dSpatrick       DumpOpts.RecoverableErrorHandler(std::move(E));
31909467b48Spatrick       return;
32009467b48Spatrick     }
32109467b48Spatrick 
32273471bf0Spatrick     Header.dump(Data, OS, DumpOpts);
32309467b48Spatrick 
32409467b48Spatrick     uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
32509467b48Spatrick     Data.setAddressSize(Header.getAddrSize());
32609467b48Spatrick     DWARFDebugLoclists Loc(Data, Header.getVersion());
32709467b48Spatrick     if (DumpOffset) {
32809467b48Spatrick       if (DumpOffset >= Offset && DumpOffset < EndOffset) {
32909467b48Spatrick         Offset = *DumpOffset;
330*d415bd75Srobert         Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,
331*d415bd75Srobert                              nullptr, DumpOpts, /*Indent=*/0);
33209467b48Spatrick         OS << "\n";
33309467b48Spatrick         return;
33409467b48Spatrick       }
33509467b48Spatrick     } else {
336*d415bd75Srobert       Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);
33709467b48Spatrick     }
33809467b48Spatrick     Offset = EndOffset;
33909467b48Spatrick   }
34009467b48Spatrick }
34109467b48Spatrick 
dumpPubTableSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,bool GnuStyle)342097a140dSpatrick static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,
343097a140dSpatrick                                 DWARFDataExtractor Data, bool GnuStyle) {
344097a140dSpatrick   DWARFDebugPubTable Table;
345097a140dSpatrick   Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);
346097a140dSpatrick   Table.dump(OS);
347097a140dSpatrick }
348097a140dSpatrick 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,std::array<std::optional<uint64_t>,DIDT_ID_Count> DumpOffsets)34909467b48Spatrick void DWARFContext::dump(
35009467b48Spatrick     raw_ostream &OS, DIDumpOptions DumpOpts,
351*d415bd75Srobert     std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
35209467b48Spatrick   uint64_t DumpType = DumpOpts.DumpType;
35309467b48Spatrick 
35409467b48Spatrick   StringRef Extension = sys::path::extension(DObj->getFileName());
35509467b48Spatrick   bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");
35609467b48Spatrick 
35709467b48Spatrick   // Print UUID header.
35809467b48Spatrick   const auto *ObjFile = DObj->getFile();
35909467b48Spatrick   if (DumpType & DIDT_UUID)
36009467b48Spatrick     dumpUUID(OS, *ObjFile);
36109467b48Spatrick 
36209467b48Spatrick   // Print a header for each explicitly-requested section.
36309467b48Spatrick   // Otherwise just print one for non-empty sections.
36409467b48Spatrick   // Only print empty .dwo section headers when dumping a .dwo file.
36509467b48Spatrick   bool Explicit = DumpType != DIDT_All && !IsDWO;
36609467b48Spatrick   bool ExplicitDWO = Explicit && IsDWO;
36709467b48Spatrick   auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,
368*d415bd75Srobert                         StringRef Section) -> std::optional<uint64_t> * {
36909467b48Spatrick     unsigned Mask = 1U << ID;
37009467b48Spatrick     bool Should = (DumpType & Mask) && (Explicit || !Section.empty());
37109467b48Spatrick     if (!Should)
37209467b48Spatrick       return nullptr;
37309467b48Spatrick     OS << "\n" << Name << " contents:\n";
37409467b48Spatrick     return &DumpOffsets[ID];
37509467b48Spatrick   };
37609467b48Spatrick 
37709467b48Spatrick   // Dump individual sections.
37809467b48Spatrick   if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,
37909467b48Spatrick                  DObj->getAbbrevSection()))
38009467b48Spatrick     getDebugAbbrev()->dump(OS);
38109467b48Spatrick   if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,
38209467b48Spatrick                  DObj->getAbbrevDWOSection()))
38309467b48Spatrick     getDebugAbbrevDWO()->dump(OS);
38409467b48Spatrick 
38509467b48Spatrick   auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
38609467b48Spatrick     OS << '\n' << Name << " contents:\n";
38709467b48Spatrick     if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
38809467b48Spatrick       for (const auto &U : Units)
389*d415bd75Srobert         U->getDIEForOffset(*DumpOffset)
39009467b48Spatrick             .dump(OS, 0, DumpOpts.noImplicitRecursion());
39109467b48Spatrick     else
39209467b48Spatrick       for (const auto &U : Units)
39309467b48Spatrick         U->dump(OS, DumpOpts);
39409467b48Spatrick   };
39509467b48Spatrick   if ((DumpType & DIDT_DebugInfo)) {
39609467b48Spatrick     if (Explicit || getNumCompileUnits())
39709467b48Spatrick       dumpDebugInfo(".debug_info", info_section_units());
39809467b48Spatrick     if (ExplicitDWO || getNumDWOCompileUnits())
39909467b48Spatrick       dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());
40009467b48Spatrick   }
40109467b48Spatrick 
40209467b48Spatrick   auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {
40309467b48Spatrick     OS << '\n' << Name << " contents:\n";
40409467b48Spatrick     for (const auto &U : Units)
40509467b48Spatrick       if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])
40609467b48Spatrick         U->getDIEForOffset(*DumpOffset)
40709467b48Spatrick             .dump(OS, 0, DumpOpts.noImplicitRecursion());
40809467b48Spatrick       else
40909467b48Spatrick         U->dump(OS, DumpOpts);
41009467b48Spatrick   };
41109467b48Spatrick   if ((DumpType & DIDT_DebugTypes)) {
41209467b48Spatrick     if (Explicit || getNumTypeUnits())
41309467b48Spatrick       dumpDebugType(".debug_types", types_section_units());
41409467b48Spatrick     if (ExplicitDWO || getNumDWOTypeUnits())
41509467b48Spatrick       dumpDebugType(".debug_types.dwo", dwo_types_section_units());
41609467b48Spatrick   }
41709467b48Spatrick 
41809467b48Spatrick   DIDumpOptions LLDumpOpts = DumpOpts;
41909467b48Spatrick   if (LLDumpOpts.Verbose)
42009467b48Spatrick     LLDumpOpts.DisplayRawContents = true;
42109467b48Spatrick 
42209467b48Spatrick   if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
42309467b48Spatrick                                    DObj->getLocSection().Data)) {
424*d415bd75Srobert     getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);
42509467b48Spatrick   }
42609467b48Spatrick   if (const auto *Off =
42709467b48Spatrick           shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
42809467b48Spatrick                      DObj->getLoclistsSection().Data)) {
42909467b48Spatrick     DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
43009467b48Spatrick                             0);
431*d415bd75Srobert     dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
43209467b48Spatrick   }
43309467b48Spatrick   if (const auto *Off =
43409467b48Spatrick           shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
43509467b48Spatrick                      DObj->getLoclistsDWOSection().Data)) {
43609467b48Spatrick     DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
43709467b48Spatrick                             isLittleEndian(), 0);
438*d415bd75Srobert     dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);
43909467b48Spatrick   }
44009467b48Spatrick 
44109467b48Spatrick   if (const auto *Off =
44209467b48Spatrick           shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
44309467b48Spatrick                      DObj->getLocDWOSection().Data)) {
44409467b48Spatrick     DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
44509467b48Spatrick                             4);
44609467b48Spatrick     DWARFDebugLoclists Loc(Data, /*Version=*/4);
44709467b48Spatrick     if (*Off) {
44809467b48Spatrick       uint64_t Offset = **Off;
44909467b48Spatrick       Loc.dumpLocationList(&Offset, OS,
450*d415bd75Srobert                            /*BaseAddr=*/std::nullopt, *DObj, nullptr,
451*d415bd75Srobert                            LLDumpOpts,
452*d415bd75Srobert                            /*Indent=*/0);
45309467b48Spatrick       OS << "\n";
45409467b48Spatrick     } else {
455*d415bd75Srobert       Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);
45609467b48Spatrick     }
45709467b48Spatrick   }
45809467b48Spatrick 
459*d415bd75Srobert   if (const std::optional<uint64_t> *Off =
460097a140dSpatrick           shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
461097a140dSpatrick                      DObj->getFrameSection().Data)) {
462097a140dSpatrick     if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())
463*d415bd75Srobert       (*DF)->dump(OS, DumpOpts, *Off);
464097a140dSpatrick     else
465097a140dSpatrick       RecoverableErrorHandler(DF.takeError());
46609467b48Spatrick   }
467097a140dSpatrick 
468*d415bd75Srobert   if (const std::optional<uint64_t> *Off =
469097a140dSpatrick           shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
470097a140dSpatrick                      DObj->getEHFrameSection().Data)) {
471097a140dSpatrick     if (Expected<const DWARFDebugFrame *> DF = getEHFrame())
472*d415bd75Srobert       (*DF)->dump(OS, DumpOpts, *Off);
473097a140dSpatrick     else
474097a140dSpatrick       RecoverableErrorHandler(DF.takeError());
475097a140dSpatrick   }
476097a140dSpatrick 
477097a140dSpatrick   if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,
478097a140dSpatrick                  DObj->getMacroSection().Data)) {
479097a140dSpatrick     if (auto Macro = getDebugMacro())
480097a140dSpatrick       Macro->dump(OS);
481097a140dSpatrick   }
482097a140dSpatrick 
483097a140dSpatrick   if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,
484097a140dSpatrick                  DObj->getMacroDWOSection())) {
485097a140dSpatrick     if (auto MacroDWO = getDebugMacroDWO())
486097a140dSpatrick       MacroDWO->dump(OS);
487097a140dSpatrick   }
488097a140dSpatrick 
489097a140dSpatrick   if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,
490097a140dSpatrick                  DObj->getMacinfoSection())) {
491097a140dSpatrick     if (auto Macinfo = getDebugMacinfo())
492097a140dSpatrick       Macinfo->dump(OS);
493097a140dSpatrick   }
494097a140dSpatrick 
495097a140dSpatrick   if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,
496097a140dSpatrick                  DObj->getMacinfoDWOSection())) {
497097a140dSpatrick     if (auto MacinfoDWO = getDebugMacinfoDWO())
498097a140dSpatrick       MacinfoDWO->dump(OS);
49909467b48Spatrick   }
50009467b48Spatrick 
50109467b48Spatrick   if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,
50209467b48Spatrick                  DObj->getArangesSection())) {
50309467b48Spatrick     uint64_t offset = 0;
504097a140dSpatrick     DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),
505097a140dSpatrick                                    0);
50609467b48Spatrick     DWARFDebugArangeSet set;
507097a140dSpatrick     while (arangesData.isValidOffset(offset)) {
50873471bf0Spatrick       if (Error E =
50973471bf0Spatrick               set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {
510097a140dSpatrick         RecoverableErrorHandler(std::move(E));
511097a140dSpatrick         break;
512097a140dSpatrick       }
51309467b48Spatrick       set.dump(OS);
51409467b48Spatrick     }
515097a140dSpatrick   }
51609467b48Spatrick 
51709467b48Spatrick   auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,
51809467b48Spatrick                              DIDumpOptions DumpOpts,
519*d415bd75Srobert                              std::optional<uint64_t> DumpOffset) {
52009467b48Spatrick     while (!Parser.done()) {
52109467b48Spatrick       if (DumpOffset && Parser.getOffset() != *DumpOffset) {
522097a140dSpatrick         Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);
52309467b48Spatrick         continue;
52409467b48Spatrick       }
52509467b48Spatrick       OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())
52609467b48Spatrick          << "]\n";
527097a140dSpatrick       Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,
528097a140dSpatrick                        DumpOpts.Verbose);
52909467b48Spatrick     }
53009467b48Spatrick   };
53109467b48Spatrick 
53273471bf0Spatrick   auto DumpStrSection = [&](StringRef Section) {
53373471bf0Spatrick     DataExtractor StrData(Section, isLittleEndian(), 0);
53473471bf0Spatrick     uint64_t Offset = 0;
53573471bf0Spatrick     uint64_t StrOffset = 0;
53673471bf0Spatrick     while (StrData.isValidOffset(Offset)) {
53773471bf0Spatrick       Error Err = Error::success();
53873471bf0Spatrick       const char *CStr = StrData.getCStr(&Offset, &Err);
53973471bf0Spatrick       if (Err) {
54073471bf0Spatrick         DumpOpts.WarningHandler(std::move(Err));
54173471bf0Spatrick         return;
54273471bf0Spatrick       }
54373471bf0Spatrick       OS << format("0x%8.8" PRIx64 ": \"", StrOffset);
54473471bf0Spatrick       OS.write_escaped(CStr);
54573471bf0Spatrick       OS << "\"\n";
54673471bf0Spatrick       StrOffset = Offset;
54773471bf0Spatrick     }
54873471bf0Spatrick   };
54973471bf0Spatrick 
55009467b48Spatrick   if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,
55109467b48Spatrick                                    DObj->getLineSection().Data)) {
55209467b48Spatrick     DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),
55309467b48Spatrick                                 0);
55473471bf0Spatrick     DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units());
55509467b48Spatrick     DumpLineSection(Parser, DumpOpts, *Off);
55609467b48Spatrick   }
55709467b48Spatrick 
55809467b48Spatrick   if (const auto *Off =
55909467b48Spatrick           shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,
56009467b48Spatrick                      DObj->getLineDWOSection().Data)) {
56109467b48Spatrick     DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),
56209467b48Spatrick                                 isLittleEndian(), 0);
56373471bf0Spatrick     DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units());
56409467b48Spatrick     DumpLineSection(Parser, DumpOpts, *Off);
56509467b48Spatrick   }
56609467b48Spatrick 
56709467b48Spatrick   if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,
56809467b48Spatrick                  DObj->getCUIndexSection())) {
56909467b48Spatrick     getCUIndex().dump(OS);
57009467b48Spatrick   }
57109467b48Spatrick 
57209467b48Spatrick   if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,
57309467b48Spatrick                  DObj->getTUIndexSection())) {
57409467b48Spatrick     getTUIndex().dump(OS);
57509467b48Spatrick   }
57609467b48Spatrick 
57709467b48Spatrick   if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,
57873471bf0Spatrick                  DObj->getStrSection()))
57973471bf0Spatrick     DumpStrSection(DObj->getStrSection());
58073471bf0Spatrick 
58109467b48Spatrick   if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,
58273471bf0Spatrick                  DObj->getStrDWOSection()))
58373471bf0Spatrick     DumpStrSection(DObj->getStrDWOSection());
58473471bf0Spatrick 
58509467b48Spatrick   if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,
58673471bf0Spatrick                  DObj->getLineStrSection()))
58773471bf0Spatrick     DumpStrSection(DObj->getLineStrSection());
58809467b48Spatrick 
58909467b48Spatrick   if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,
59009467b48Spatrick                  DObj->getAddrSection().Data)) {
59109467b48Spatrick     DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),
59209467b48Spatrick                                    isLittleEndian(), 0);
59309467b48Spatrick     dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());
59409467b48Spatrick   }
59509467b48Spatrick 
59609467b48Spatrick   if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,
59709467b48Spatrick                  DObj->getRangesSection().Data)) {
59809467b48Spatrick     uint8_t savedAddressByteSize = getCUAddrSize();
59909467b48Spatrick     DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),
60009467b48Spatrick                                   isLittleEndian(), savedAddressByteSize);
60109467b48Spatrick     uint64_t offset = 0;
60209467b48Spatrick     DWARFDebugRangeList rangeList;
60309467b48Spatrick     while (rangesData.isValidOffset(offset)) {
60409467b48Spatrick       if (Error E = rangeList.extract(rangesData, &offset)) {
605097a140dSpatrick         DumpOpts.RecoverableErrorHandler(std::move(E));
60609467b48Spatrick         break;
60709467b48Spatrick       }
60809467b48Spatrick       rangeList.dump(OS);
60909467b48Spatrick     }
61009467b48Spatrick   }
61109467b48Spatrick 
612*d415bd75Srobert   auto LookupPooledAddress =
613*d415bd75Srobert       [&](uint32_t Index) -> std::optional<SectionedAddress> {
61409467b48Spatrick     const auto &CUs = compile_units();
61509467b48Spatrick     auto I = CUs.begin();
61609467b48Spatrick     if (I == CUs.end())
617*d415bd75Srobert       return std::nullopt;
61809467b48Spatrick     return (*I)->getAddrOffsetSectionItem(Index);
61909467b48Spatrick   };
62009467b48Spatrick 
62109467b48Spatrick   if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,
62209467b48Spatrick                  DObj->getRnglistsSection().Data)) {
62309467b48Spatrick     DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),
62409467b48Spatrick                                    isLittleEndian(), 0);
62509467b48Spatrick     dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
62609467b48Spatrick   }
62709467b48Spatrick 
62809467b48Spatrick   if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,
62909467b48Spatrick                  DObj->getRnglistsDWOSection().Data)) {
63009467b48Spatrick     DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),
63109467b48Spatrick                                    isLittleEndian(), 0);
63209467b48Spatrick     dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);
63309467b48Spatrick   }
63409467b48Spatrick 
63509467b48Spatrick   if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,
636097a140dSpatrick                  DObj->getPubnamesSection().Data)) {
637097a140dSpatrick     DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),
638097a140dSpatrick                                     isLittleEndian(), 0);
639097a140dSpatrick     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
640097a140dSpatrick   }
64109467b48Spatrick 
64209467b48Spatrick   if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,
643097a140dSpatrick                  DObj->getPubtypesSection().Data)) {
644097a140dSpatrick     DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),
645097a140dSpatrick                                     isLittleEndian(), 0);
646097a140dSpatrick     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);
647097a140dSpatrick   }
64809467b48Spatrick 
64909467b48Spatrick   if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,
650097a140dSpatrick                  DObj->getGnuPubnamesSection().Data)) {
651097a140dSpatrick     DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),
652097a140dSpatrick                                     isLittleEndian(), 0);
653097a140dSpatrick     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
654097a140dSpatrick   }
65509467b48Spatrick 
65609467b48Spatrick   if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,
657097a140dSpatrick                  DObj->getGnuPubtypesSection().Data)) {
658097a140dSpatrick     DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),
659097a140dSpatrick                                     isLittleEndian(), 0);
660097a140dSpatrick     dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);
661097a140dSpatrick   }
66209467b48Spatrick 
66309467b48Spatrick   if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,
66409467b48Spatrick                  DObj->getStrOffsetsSection().Data))
665097a140dSpatrick     dumpStringOffsetsSection(
666097a140dSpatrick         OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),
667097a140dSpatrick         DObj->getStrSection(), normal_units(), isLittleEndian());
66809467b48Spatrick   if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,
66909467b48Spatrick                  DObj->getStrOffsetsDWOSection().Data))
670097a140dSpatrick     dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,
67109467b48Spatrick                              DObj->getStrOffsetsDWOSection(),
67209467b48Spatrick                              DObj->getStrDWOSection(), dwo_units(),
673097a140dSpatrick                              isLittleEndian());
67409467b48Spatrick 
67509467b48Spatrick   if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,
67609467b48Spatrick                  DObj->getGdbIndexSection())) {
67709467b48Spatrick     getGdbIndex().dump(OS);
67809467b48Spatrick   }
67909467b48Spatrick 
68009467b48Spatrick   if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,
68109467b48Spatrick                  DObj->getAppleNamesSection().Data))
68209467b48Spatrick     getAppleNames().dump(OS);
68309467b48Spatrick 
68409467b48Spatrick   if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,
68509467b48Spatrick                  DObj->getAppleTypesSection().Data))
68609467b48Spatrick     getAppleTypes().dump(OS);
68709467b48Spatrick 
68809467b48Spatrick   if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,
68909467b48Spatrick                  DObj->getAppleNamespacesSection().Data))
69009467b48Spatrick     getAppleNamespaces().dump(OS);
69109467b48Spatrick 
69209467b48Spatrick   if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,
69309467b48Spatrick                  DObj->getAppleObjCSection().Data))
69409467b48Spatrick     getAppleObjC().dump(OS);
69509467b48Spatrick   if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,
69609467b48Spatrick                  DObj->getNamesSection().Data))
69709467b48Spatrick     getDebugNames().dump(OS);
69809467b48Spatrick }
69909467b48Spatrick 
getTypeUnitForHash(uint16_t Version,uint64_t Hash,bool IsDWO)700*d415bd75Srobert DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,
701*d415bd75Srobert                                                 bool IsDWO) {
702*d415bd75Srobert   parseDWOUnits(LazyParse);
703*d415bd75Srobert 
704*d415bd75Srobert   if (const auto &TUI = getTUIndex()) {
705*d415bd75Srobert     if (const auto *R = TUI.getFromHash(Hash))
706*d415bd75Srobert       return dyn_cast_or_null<DWARFTypeUnit>(
707*d415bd75Srobert           DWOUnits.getUnitForIndexEntry(*R));
708*d415bd75Srobert     return nullptr;
709*d415bd75Srobert   }
710*d415bd75Srobert 
711*d415bd75Srobert   struct UnitContainers {
712*d415bd75Srobert     const DWARFUnitVector &Units;
713*d415bd75Srobert     std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> &Map;
714*d415bd75Srobert   };
715*d415bd75Srobert   UnitContainers Units = IsDWO ? UnitContainers{DWOUnits, DWOTypeUnits}
716*d415bd75Srobert                                : UnitContainers{NormalUnits, NormalTypeUnits};
717*d415bd75Srobert   if (!Units.Map) {
718*d415bd75Srobert     Units.Map.emplace();
719*d415bd75Srobert     for (const auto &U : IsDWO ? dwo_units() : normal_units()) {
720*d415bd75Srobert       if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))
721*d415bd75Srobert         (*Units.Map)[TU->getTypeHash()] = TU;
722*d415bd75Srobert     }
723*d415bd75Srobert   }
724*d415bd75Srobert 
725*d415bd75Srobert   return (*Units.Map)[Hash];
726*d415bd75Srobert }
727*d415bd75Srobert 
getDWOCompileUnitForHash(uint64_t Hash)72809467b48Spatrick DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
72909467b48Spatrick   parseDWOUnits(LazyParse);
73009467b48Spatrick 
73109467b48Spatrick   if (const auto &CUI = getCUIndex()) {
73209467b48Spatrick     if (const auto *R = CUI.getFromHash(Hash))
73309467b48Spatrick       return dyn_cast_or_null<DWARFCompileUnit>(
73409467b48Spatrick           DWOUnits.getUnitForIndexEntry(*R));
73509467b48Spatrick     return nullptr;
73609467b48Spatrick   }
73709467b48Spatrick 
73809467b48Spatrick   // If there's no index, just search through the CUs in the DWO - there's
73909467b48Spatrick   // probably only one unless this is something like LTO - though an in-process
74009467b48Spatrick   // built/cached lookup table could be used in that case to improve repeated
74109467b48Spatrick   // lookups of different CUs in the DWO.
74209467b48Spatrick   for (const auto &DWOCU : dwo_compile_units()) {
74309467b48Spatrick     // Might not have parsed DWO ID yet.
74409467b48Spatrick     if (!DWOCU->getDWOId()) {
745*d415bd75Srobert       if (std::optional<uint64_t> DWOId =
74609467b48Spatrick               toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))
74709467b48Spatrick         DWOCU->setDWOId(*DWOId);
74809467b48Spatrick       else
74909467b48Spatrick         // No DWO ID?
75009467b48Spatrick         continue;
75109467b48Spatrick     }
75209467b48Spatrick     if (DWOCU->getDWOId() == Hash)
75309467b48Spatrick       return dyn_cast<DWARFCompileUnit>(DWOCU.get());
75409467b48Spatrick   }
75509467b48Spatrick   return nullptr;
75609467b48Spatrick }
75709467b48Spatrick 
getDIEForOffset(uint64_t Offset)75809467b48Spatrick DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) {
75909467b48Spatrick   parseNormalUnits();
76009467b48Spatrick   if (auto *CU = NormalUnits.getUnitForOffset(Offset))
76109467b48Spatrick     return CU->getDIEForOffset(Offset);
76209467b48Spatrick   return DWARFDie();
76309467b48Spatrick }
76409467b48Spatrick 
verify(raw_ostream & OS,DIDumpOptions DumpOpts)76509467b48Spatrick bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
76609467b48Spatrick   bool Success = true;
76709467b48Spatrick   DWARFVerifier verifier(OS, *this, DumpOpts);
76809467b48Spatrick 
76909467b48Spatrick   Success &= verifier.handleDebugAbbrev();
770*d415bd75Srobert   if (DumpOpts.DumpType & DIDT_DebugCUIndex)
771*d415bd75Srobert     Success &= verifier.handleDebugCUIndex();
772*d415bd75Srobert   if (DumpOpts.DumpType & DIDT_DebugTUIndex)
773*d415bd75Srobert     Success &= verifier.handleDebugTUIndex();
77409467b48Spatrick   if (DumpOpts.DumpType & DIDT_DebugInfo)
77509467b48Spatrick     Success &= verifier.handleDebugInfo();
77609467b48Spatrick   if (DumpOpts.DumpType & DIDT_DebugLine)
77709467b48Spatrick     Success &= verifier.handleDebugLine();
77809467b48Spatrick   Success &= verifier.handleAccelTables();
77909467b48Spatrick   return Success;
78009467b48Spatrick }
78109467b48Spatrick 
fixupIndex(const DWARFObject & DObj,DWARFContext & C,DWARFUnitIndex & Index)782*d415bd75Srobert void fixupIndex(const DWARFObject &DObj, DWARFContext &C,
783*d415bd75Srobert                 DWARFUnitIndex &Index) {
784*d415bd75Srobert   using EntryType = DWARFUnitIndex::Entry::SectionContribution;
785*d415bd75Srobert   using EntryMap = DenseMap<uint32_t, EntryType>;
786*d415bd75Srobert   EntryMap Map;
787*d415bd75Srobert   if (DObj.getCUIndexSection().empty())
788*d415bd75Srobert     return;
789*d415bd75Srobert 
790*d415bd75Srobert   uint64_t Offset = 0;
791*d415bd75Srobert   uint32_t TruncOffset = 0;
792*d415bd75Srobert   DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
793*d415bd75Srobert     if (!(C.getParseCUTUIndexManually() ||
794*d415bd75Srobert           S.Data.size() >= std::numeric_limits<uint32_t>::max()))
795*d415bd75Srobert       return;
796*d415bd75Srobert 
797*d415bd75Srobert     DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
798*d415bd75Srobert     while (Data.isValidOffset(Offset)) {
799*d415bd75Srobert       DWARFUnitHeader Header;
800*d415bd75Srobert       if (!Header.extract(C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
801*d415bd75Srobert         logAllUnhandledErrors(
802*d415bd75Srobert             createError("Failed to parse CU header in DWP file"), errs());
803*d415bd75Srobert         Map.clear();
804*d415bd75Srobert         break;
805*d415bd75Srobert       }
806*d415bd75Srobert 
807*d415bd75Srobert       auto Iter = Map.insert({TruncOffset,
808*d415bd75Srobert                               {Header.getOffset(), Header.getNextUnitOffset() -
809*d415bd75Srobert                                                        Header.getOffset()}});
810*d415bd75Srobert       if (!Iter.second) {
811*d415bd75Srobert         logAllUnhandledErrors(
812*d415bd75Srobert             createError("Collision occured between for truncated offset 0x" +
813*d415bd75Srobert                         Twine::utohexstr(TruncOffset)),
814*d415bd75Srobert             errs());
815*d415bd75Srobert         Map.clear();
816*d415bd75Srobert         return;
817*d415bd75Srobert       }
818*d415bd75Srobert 
819*d415bd75Srobert       Offset = Header.getNextUnitOffset();
820*d415bd75Srobert       TruncOffset = Offset;
821*d415bd75Srobert     }
822*d415bd75Srobert   });
823*d415bd75Srobert 
824*d415bd75Srobert   if (Map.empty())
825*d415bd75Srobert     return;
826*d415bd75Srobert 
827*d415bd75Srobert   for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
828*d415bd75Srobert     if (!E.isValid())
829*d415bd75Srobert       continue;
830*d415bd75Srobert     DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
831*d415bd75Srobert     auto Iter = Map.find(CUOff.getOffset());
832*d415bd75Srobert     if (Iter == Map.end()) {
833*d415bd75Srobert       logAllUnhandledErrors(createError("Could not find CU offset 0x" +
834*d415bd75Srobert                                         Twine::utohexstr(CUOff.getOffset()) +
835*d415bd75Srobert                                         " in the Map"),
836*d415bd75Srobert                             errs());
837*d415bd75Srobert       break;
838*d415bd75Srobert     }
839*d415bd75Srobert     CUOff.setOffset(Iter->second.getOffset());
840*d415bd75Srobert     if (CUOff.getOffset() != Iter->second.getOffset())
841*d415bd75Srobert       logAllUnhandledErrors(createError("Length of CU in CU index doesn't "
842*d415bd75Srobert                                         "match calculated length at offset 0x" +
843*d415bd75Srobert                                         Twine::utohexstr(CUOff.getOffset())),
844*d415bd75Srobert                             errs());
845*d415bd75Srobert   }
846*d415bd75Srobert 
847*d415bd75Srobert   return;
848*d415bd75Srobert }
849*d415bd75Srobert 
getCUIndex()85009467b48Spatrick const DWARFUnitIndex &DWARFContext::getCUIndex() {
85109467b48Spatrick   if (CUIndex)
85209467b48Spatrick     return *CUIndex;
85309467b48Spatrick 
85409467b48Spatrick   DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
85509467b48Spatrick   CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
85609467b48Spatrick   CUIndex->parse(CUIndexData);
857*d415bd75Srobert   fixupIndex(*DObj, *this, *CUIndex.get());
85809467b48Spatrick   return *CUIndex;
85909467b48Spatrick }
86009467b48Spatrick 
getTUIndex()86109467b48Spatrick const DWARFUnitIndex &DWARFContext::getTUIndex() {
86209467b48Spatrick   if (TUIndex)
86309467b48Spatrick     return *TUIndex;
86409467b48Spatrick 
86509467b48Spatrick   DataExtractor TUIndexData(DObj->getTUIndexSection(), isLittleEndian(), 0);
866097a140dSpatrick   TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);
867*d415bd75Srobert   bool isParseSuccessful = TUIndex->parse(TUIndexData);
868*d415bd75Srobert   // If we are parsing TU-index and for .debug_types section we don't need
869*d415bd75Srobert   // to do anything.
870*d415bd75Srobert   if (isParseSuccessful && TUIndex->getVersion() != 2)
871*d415bd75Srobert     fixupIndex(*DObj, *this, *TUIndex.get());
87209467b48Spatrick   return *TUIndex;
87309467b48Spatrick }
87409467b48Spatrick 
getGdbIndex()87509467b48Spatrick DWARFGdbIndex &DWARFContext::getGdbIndex() {
87609467b48Spatrick   if (GdbIndex)
87709467b48Spatrick     return *GdbIndex;
87809467b48Spatrick 
87909467b48Spatrick   DataExtractor GdbIndexData(DObj->getGdbIndexSection(), true /*LE*/, 0);
88009467b48Spatrick   GdbIndex = std::make_unique<DWARFGdbIndex>();
88109467b48Spatrick   GdbIndex->parse(GdbIndexData);
88209467b48Spatrick   return *GdbIndex;
88309467b48Spatrick }
88409467b48Spatrick 
getDebugAbbrev()88509467b48Spatrick const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
88609467b48Spatrick   if (Abbrev)
88709467b48Spatrick     return Abbrev.get();
88809467b48Spatrick 
88909467b48Spatrick   DataExtractor abbrData(DObj->getAbbrevSection(), isLittleEndian(), 0);
89009467b48Spatrick 
89109467b48Spatrick   Abbrev.reset(new DWARFDebugAbbrev());
89209467b48Spatrick   Abbrev->extract(abbrData);
89309467b48Spatrick   return Abbrev.get();
89409467b48Spatrick }
89509467b48Spatrick 
getDebugAbbrevDWO()89609467b48Spatrick const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
89709467b48Spatrick   if (AbbrevDWO)
89809467b48Spatrick     return AbbrevDWO.get();
89909467b48Spatrick 
90009467b48Spatrick   DataExtractor abbrData(DObj->getAbbrevDWOSection(), isLittleEndian(), 0);
90109467b48Spatrick   AbbrevDWO.reset(new DWARFDebugAbbrev());
90209467b48Spatrick   AbbrevDWO->extract(abbrData);
90309467b48Spatrick   return AbbrevDWO.get();
90409467b48Spatrick }
90509467b48Spatrick 
getDebugLoc()90609467b48Spatrick const DWARFDebugLoc *DWARFContext::getDebugLoc() {
90709467b48Spatrick   if (Loc)
90809467b48Spatrick     return Loc.get();
90909467b48Spatrick 
91009467b48Spatrick   // Assume all units have the same address byte size.
91109467b48Spatrick   auto LocData =
91209467b48Spatrick       getNumCompileUnits()
91309467b48Spatrick           ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(),
91409467b48Spatrick                                getUnitAtIndex(0)->getAddressByteSize())
91509467b48Spatrick           : DWARFDataExtractor("", isLittleEndian(), 0);
91609467b48Spatrick   Loc.reset(new DWARFDebugLoc(std::move(LocData)));
91709467b48Spatrick   return Loc.get();
91809467b48Spatrick }
91909467b48Spatrick 
getDebugAranges()92009467b48Spatrick const DWARFDebugAranges *DWARFContext::getDebugAranges() {
92109467b48Spatrick   if (Aranges)
92209467b48Spatrick     return Aranges.get();
92309467b48Spatrick 
92409467b48Spatrick   Aranges.reset(new DWARFDebugAranges());
92509467b48Spatrick   Aranges->generate(this);
92609467b48Spatrick   return Aranges.get();
92709467b48Spatrick }
92809467b48Spatrick 
getDebugFrame()929097a140dSpatrick Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {
93009467b48Spatrick   if (DebugFrame)
93109467b48Spatrick     return DebugFrame.get();
93209467b48Spatrick 
93373471bf0Spatrick   const DWARFSection &DS = DObj->getFrameSection();
93473471bf0Spatrick 
93509467b48Spatrick   // There's a "bug" in the DWARFv3 standard with respect to the target address
93609467b48Spatrick   // size within debug frame sections. While DWARF is supposed to be independent
93709467b48Spatrick   // of its container, FDEs have fields with size being "target address size",
93809467b48Spatrick   // which isn't specified in DWARF in general. It's only specified for CUs, but
93909467b48Spatrick   // .eh_frame can appear without a .debug_info section. Follow the example of
94009467b48Spatrick   // other tools (libdwarf) and extract this from the container (ObjectFile
94109467b48Spatrick   // provides this information). This problem is fixed in DWARFv4
94209467b48Spatrick   // See this dwarf-discuss discussion for more details:
94309467b48Spatrick   // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
94473471bf0Spatrick   DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
94573471bf0Spatrick                                     DObj->getAddressSize());
94673471bf0Spatrick   auto DF =
94773471bf0Spatrick       std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false, DS.Address);
94873471bf0Spatrick   if (Error E = DF->parse(DebugFrameData))
949097a140dSpatrick     return std::move(E);
950097a140dSpatrick 
951097a140dSpatrick   DebugFrame.swap(DF);
95209467b48Spatrick   return DebugFrame.get();
95309467b48Spatrick }
95409467b48Spatrick 
getEHFrame()955097a140dSpatrick Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {
95609467b48Spatrick   if (EHFrame)
95709467b48Spatrick     return EHFrame.get();
95809467b48Spatrick 
95973471bf0Spatrick   const DWARFSection &DS = DObj->getEHFrameSection();
96073471bf0Spatrick   DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(),
96173471bf0Spatrick                                     DObj->getAddressSize());
962097a140dSpatrick 
96373471bf0Spatrick   auto DF =
96473471bf0Spatrick       std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true, DS.Address);
96573471bf0Spatrick   if (Error E = DF->parse(DebugFrameData))
966097a140dSpatrick     return std::move(E);
967097a140dSpatrick   DebugFrame.swap(DF);
96809467b48Spatrick   return DebugFrame.get();
96909467b48Spatrick }
97009467b48Spatrick 
getDebugMacro()971097a140dSpatrick const DWARFDebugMacro *DWARFContext::getDebugMacro() {
972097a140dSpatrick   if (!Macro)
973097a140dSpatrick     Macro = parseMacroOrMacinfo(MacroSection);
974097a140dSpatrick   return Macro.get();
975097a140dSpatrick }
97609467b48Spatrick 
getDebugMacroDWO()977097a140dSpatrick const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
978097a140dSpatrick   if (!MacroDWO)
979097a140dSpatrick     MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
98009467b48Spatrick   return MacroDWO.get();
98109467b48Spatrick }
98209467b48Spatrick 
getDebugMacinfo()983097a140dSpatrick const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {
984097a140dSpatrick   if (!Macinfo)
985097a140dSpatrick     Macinfo = parseMacroOrMacinfo(MacinfoSection);
986097a140dSpatrick   return Macinfo.get();
987097a140dSpatrick }
98809467b48Spatrick 
getDebugMacinfoDWO()989097a140dSpatrick const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
990097a140dSpatrick   if (!MacinfoDWO)
991097a140dSpatrick     MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
992097a140dSpatrick   return MacinfoDWO.get();
99309467b48Spatrick }
99409467b48Spatrick 
99509467b48Spatrick template <typename T>
getAccelTable(std::unique_ptr<T> & Cache,const DWARFObject & Obj,const DWARFSection & Section,StringRef StringSection,bool IsLittleEndian)99609467b48Spatrick static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,
99709467b48Spatrick                         const DWARFSection &Section, StringRef StringSection,
99809467b48Spatrick                         bool IsLittleEndian) {
99909467b48Spatrick   if (Cache)
100009467b48Spatrick     return *Cache;
100109467b48Spatrick   DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);
100209467b48Spatrick   DataExtractor StrData(StringSection, IsLittleEndian, 0);
100309467b48Spatrick   Cache.reset(new T(AccelSection, StrData));
100409467b48Spatrick   if (Error E = Cache->extract())
100509467b48Spatrick     llvm::consumeError(std::move(E));
100609467b48Spatrick   return *Cache;
100709467b48Spatrick }
100809467b48Spatrick 
getDebugNames()100909467b48Spatrick const DWARFDebugNames &DWARFContext::getDebugNames() {
101009467b48Spatrick   return getAccelTable(Names, *DObj, DObj->getNamesSection(),
101109467b48Spatrick                        DObj->getStrSection(), isLittleEndian());
101209467b48Spatrick }
101309467b48Spatrick 
getAppleNames()101409467b48Spatrick const AppleAcceleratorTable &DWARFContext::getAppleNames() {
101509467b48Spatrick   return getAccelTable(AppleNames, *DObj, DObj->getAppleNamesSection(),
101609467b48Spatrick                        DObj->getStrSection(), isLittleEndian());
101709467b48Spatrick }
101809467b48Spatrick 
getAppleTypes()101909467b48Spatrick const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
102009467b48Spatrick   return getAccelTable(AppleTypes, *DObj, DObj->getAppleTypesSection(),
102109467b48Spatrick                        DObj->getStrSection(), isLittleEndian());
102209467b48Spatrick }
102309467b48Spatrick 
getAppleNamespaces()102409467b48Spatrick const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
102509467b48Spatrick   return getAccelTable(AppleNamespaces, *DObj,
102609467b48Spatrick                        DObj->getAppleNamespacesSection(),
102709467b48Spatrick                        DObj->getStrSection(), isLittleEndian());
102809467b48Spatrick }
102909467b48Spatrick 
getAppleObjC()103009467b48Spatrick const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
103109467b48Spatrick   return getAccelTable(AppleObjC, *DObj, DObj->getAppleObjCSection(),
103209467b48Spatrick                        DObj->getStrSection(), isLittleEndian());
103309467b48Spatrick }
103409467b48Spatrick 
103509467b48Spatrick const DWARFDebugLine::LineTable *
getLineTableForUnit(DWARFUnit * U)103609467b48Spatrick DWARFContext::getLineTableForUnit(DWARFUnit *U) {
103709467b48Spatrick   Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =
1038097a140dSpatrick       getLineTableForUnit(U, WarningHandler);
103909467b48Spatrick   if (!ExpectedLineTable) {
1040097a140dSpatrick     WarningHandler(ExpectedLineTable.takeError());
104109467b48Spatrick     return nullptr;
104209467b48Spatrick   }
104309467b48Spatrick   return *ExpectedLineTable;
104409467b48Spatrick }
104509467b48Spatrick 
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)104609467b48Spatrick Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
1047097a140dSpatrick     DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
104809467b48Spatrick   if (!Line)
104909467b48Spatrick     Line.reset(new DWARFDebugLine);
105009467b48Spatrick 
105109467b48Spatrick   auto UnitDIE = U->getUnitDIE();
105209467b48Spatrick   if (!UnitDIE)
105309467b48Spatrick     return nullptr;
105409467b48Spatrick 
105509467b48Spatrick   auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
105609467b48Spatrick   if (!Offset)
105709467b48Spatrick     return nullptr; // No line table for this compile unit.
105809467b48Spatrick 
105909467b48Spatrick   uint64_t stmtOffset = *Offset + U->getLineTableOffset();
106009467b48Spatrick   // See if the line table is cached.
106109467b48Spatrick   if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
106209467b48Spatrick     return lt;
106309467b48Spatrick 
106409467b48Spatrick   // Make sure the offset is good before we try to parse.
106509467b48Spatrick   if (stmtOffset >= U->getLineSection().Data.size())
106609467b48Spatrick     return nullptr;
106709467b48Spatrick 
106809467b48Spatrick   // We have to parse it first.
106909467b48Spatrick   DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(),
107009467b48Spatrick                               U->getAddressByteSize());
107109467b48Spatrick   return Line->getOrParseLineTable(lineData, stmtOffset, *this, U,
1072097a140dSpatrick                                    RecoverableErrorHandler);
107309467b48Spatrick }
107409467b48Spatrick 
clearLineTableForUnit(DWARFUnit * U)1075*d415bd75Srobert void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {
1076*d415bd75Srobert   if (!Line)
1077*d415bd75Srobert     return;
1078*d415bd75Srobert 
1079*d415bd75Srobert   auto UnitDIE = U->getUnitDIE();
1080*d415bd75Srobert   if (!UnitDIE)
1081*d415bd75Srobert     return;
1082*d415bd75Srobert 
1083*d415bd75Srobert   auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
1084*d415bd75Srobert   if (!Offset)
1085*d415bd75Srobert     return;
1086*d415bd75Srobert 
1087*d415bd75Srobert   uint64_t stmtOffset = *Offset + U->getLineTableOffset();
1088*d415bd75Srobert   Line->clearLineTable(stmtOffset);
1089*d415bd75Srobert }
1090*d415bd75Srobert 
parseNormalUnits()109109467b48Spatrick void DWARFContext::parseNormalUnits() {
109209467b48Spatrick   if (!NormalUnits.empty())
109309467b48Spatrick     return;
109409467b48Spatrick   DObj->forEachInfoSections([&](const DWARFSection &S) {
109509467b48Spatrick     NormalUnits.addUnitsForSection(*this, S, DW_SECT_INFO);
109609467b48Spatrick   });
109709467b48Spatrick   NormalUnits.finishedInfoUnits();
109809467b48Spatrick   DObj->forEachTypesSections([&](const DWARFSection &S) {
1099097a140dSpatrick     NormalUnits.addUnitsForSection(*this, S, DW_SECT_EXT_TYPES);
110009467b48Spatrick   });
110109467b48Spatrick }
110209467b48Spatrick 
parseDWOUnits(bool Lazy)110309467b48Spatrick void DWARFContext::parseDWOUnits(bool Lazy) {
110409467b48Spatrick   if (!DWOUnits.empty())
110509467b48Spatrick     return;
110609467b48Spatrick   DObj->forEachInfoDWOSections([&](const DWARFSection &S) {
110709467b48Spatrick     DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_INFO, Lazy);
110809467b48Spatrick   });
110909467b48Spatrick   DWOUnits.finishedInfoUnits();
111009467b48Spatrick   DObj->forEachTypesDWOSections([&](const DWARFSection &S) {
1111097a140dSpatrick     DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_EXT_TYPES, Lazy);
111209467b48Spatrick   });
111309467b48Spatrick }
111409467b48Spatrick 
getCompileUnitForOffset(uint64_t Offset)111509467b48Spatrick DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {
111609467b48Spatrick   parseNormalUnits();
111709467b48Spatrick   return dyn_cast_or_null<DWARFCompileUnit>(
111809467b48Spatrick       NormalUnits.getUnitForOffset(Offset));
111909467b48Spatrick }
112009467b48Spatrick 
getCompileUnitForAddress(uint64_t Address)112109467b48Spatrick DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
112209467b48Spatrick   // First, get the offset of the compile unit.
112309467b48Spatrick   uint64_t CUOffset = getDebugAranges()->findAddress(Address);
112409467b48Spatrick   // Retrieve the compile unit.
1125*d415bd75Srobert   if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))
1126*d415bd75Srobert     return OffsetCU;
1127*d415bd75Srobert 
1128*d415bd75Srobert   // Global variables are often not found by the above search, for one of two
1129*d415bd75Srobert   // reasons:
1130*d415bd75Srobert   //   1. .debug_aranges may not include global variables. On clang, it seems we
1131*d415bd75Srobert   //      put the globals in the aranges, but this isn't true for gcc.
1132*d415bd75Srobert   //   2. Even if the global variable is in a .debug_arange, global variables
1133*d415bd75Srobert   //      may not be captured in the [start, end) addresses described by the
1134*d415bd75Srobert   //      parent compile unit.
1135*d415bd75Srobert   //
1136*d415bd75Srobert   // So, we walk the CU's and their child DI's manually, looking for the
1137*d415bd75Srobert   // specific global variable.
1138*d415bd75Srobert   for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {
1139*d415bd75Srobert     if (DWARFDie Die = CU->getVariableForAddress(Address)) {
1140*d415bd75Srobert       return static_cast<DWARFCompileUnit *>(CU.get());
1141*d415bd75Srobert     }
1142*d415bd75Srobert   }
1143*d415bd75Srobert   return nullptr;
114409467b48Spatrick }
114509467b48Spatrick 
getDIEsForAddress(uint64_t Address)114609467b48Spatrick DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
114709467b48Spatrick   DIEsForAddress Result;
114809467b48Spatrick 
114909467b48Spatrick   DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
115009467b48Spatrick   if (!CU)
115109467b48Spatrick     return Result;
115209467b48Spatrick 
115309467b48Spatrick   Result.CompileUnit = CU;
115409467b48Spatrick   Result.FunctionDIE = CU->getSubroutineForAddress(Address);
115509467b48Spatrick 
115609467b48Spatrick   std::vector<DWARFDie> Worklist;
115709467b48Spatrick   Worklist.push_back(Result.FunctionDIE);
115809467b48Spatrick   while (!Worklist.empty()) {
115909467b48Spatrick     DWARFDie DIE = Worklist.back();
116009467b48Spatrick     Worklist.pop_back();
116109467b48Spatrick 
116209467b48Spatrick     if (!DIE.isValid())
116309467b48Spatrick       continue;
116409467b48Spatrick 
116509467b48Spatrick     if (DIE.getTag() == DW_TAG_lexical_block &&
116609467b48Spatrick         DIE.addressRangeContainsAddress(Address)) {
116709467b48Spatrick       Result.BlockDIE = DIE;
116809467b48Spatrick       break;
116909467b48Spatrick     }
117009467b48Spatrick 
117173471bf0Spatrick     append_range(Worklist, DIE);
117209467b48Spatrick   }
117309467b48Spatrick 
117409467b48Spatrick   return Result;
117509467b48Spatrick }
117609467b48Spatrick 
117709467b48Spatrick /// TODO: change input parameter from "uint64_t Address"
117809467b48Spatrick ///       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)117973471bf0Spatrick static bool getFunctionNameAndStartLineForAddress(
118073471bf0Spatrick     DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,
118173471bf0Spatrick     DILineInfoSpecifier::FileLineInfoKind FileNameKind,
118273471bf0Spatrick     std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,
1183*d415bd75Srobert     std::optional<uint64_t> &StartAddress) {
118409467b48Spatrick   // The address may correspond to instruction in some inlined function,
118509467b48Spatrick   // so we have to build the chain of inlined functions and take the
118609467b48Spatrick   // name of the topmost function in it.
118709467b48Spatrick   SmallVector<DWARFDie, 4> InlinedChain;
118809467b48Spatrick   CU->getInlinedChainForAddress(Address, InlinedChain);
118909467b48Spatrick   if (InlinedChain.empty())
119009467b48Spatrick     return false;
119109467b48Spatrick 
119209467b48Spatrick   const DWARFDie &DIE = InlinedChain[0];
119309467b48Spatrick   bool FoundResult = false;
119409467b48Spatrick   const char *Name = nullptr;
119509467b48Spatrick   if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
119609467b48Spatrick     FunctionName = Name;
119709467b48Spatrick     FoundResult = true;
119809467b48Spatrick   }
119973471bf0Spatrick   std::string DeclFile = DIE.getDeclFile(FileNameKind);
120073471bf0Spatrick   if (!DeclFile.empty()) {
120173471bf0Spatrick     StartFile = DeclFile;
120273471bf0Spatrick     FoundResult = true;
120373471bf0Spatrick   }
120409467b48Spatrick   if (auto DeclLineResult = DIE.getDeclLine()) {
120509467b48Spatrick     StartLine = DeclLineResult;
120609467b48Spatrick     FoundResult = true;
120709467b48Spatrick   }
120873471bf0Spatrick   if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))
120973471bf0Spatrick     StartAddress = LowPcAddr->Address;
121009467b48Spatrick   return FoundResult;
121109467b48Spatrick }
121209467b48Spatrick 
1213*d415bd75Srobert static std::optional<int64_t>
getExpressionFrameOffset(ArrayRef<uint8_t> Expr,std::optional<unsigned> FrameBaseReg)121409467b48Spatrick getExpressionFrameOffset(ArrayRef<uint8_t> Expr,
1215*d415bd75Srobert                          std::optional<unsigned> FrameBaseReg) {
121609467b48Spatrick   if (!Expr.empty() &&
121709467b48Spatrick       (Expr[0] == DW_OP_fbreg ||
121809467b48Spatrick        (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
121909467b48Spatrick     unsigned Count;
122009467b48Spatrick     int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
122109467b48Spatrick     // A single DW_OP_fbreg or DW_OP_breg.
122209467b48Spatrick     if (Expr.size() == Count + 1)
122309467b48Spatrick       return Offset;
122409467b48Spatrick     // Same + DW_OP_deref (Fortran arrays look like this).
122509467b48Spatrick     if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
122609467b48Spatrick       return Offset;
122709467b48Spatrick     // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
122809467b48Spatrick   }
1229*d415bd75Srobert   return std::nullopt;
123009467b48Spatrick }
123109467b48Spatrick 
addLocalsForDie(DWARFCompileUnit * CU,DWARFDie Subprogram,DWARFDie Die,std::vector<DILocal> & Result)123209467b48Spatrick void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
123309467b48Spatrick                                    DWARFDie Die, std::vector<DILocal> &Result) {
123409467b48Spatrick   if (Die.getTag() == DW_TAG_variable ||
123509467b48Spatrick       Die.getTag() == DW_TAG_formal_parameter) {
123609467b48Spatrick     DILocal Local;
123709467b48Spatrick     if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
123809467b48Spatrick       Local.FunctionName = Name;
123909467b48Spatrick 
1240*d415bd75Srobert     std::optional<unsigned> FrameBaseReg;
124109467b48Spatrick     if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
1242*d415bd75Srobert       if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
124309467b48Spatrick         if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
124409467b48Spatrick             (*Expr)[0] <= DW_OP_reg31) {
124509467b48Spatrick           FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
124609467b48Spatrick         }
124709467b48Spatrick 
124809467b48Spatrick     if (Expected<std::vector<DWARFLocationExpression>> Loc =
124909467b48Spatrick             Die.getLocations(DW_AT_location)) {
125009467b48Spatrick       for (const auto &Entry : *Loc) {
1251*d415bd75Srobert         if (std::optional<int64_t> FrameOffset =
125209467b48Spatrick                 getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
125309467b48Spatrick           Local.FrameOffset = *FrameOffset;
125409467b48Spatrick           break;
125509467b48Spatrick         }
125609467b48Spatrick       }
125709467b48Spatrick     } else {
125809467b48Spatrick       // FIXME: missing DW_AT_location is OK here, but other errors should be
125909467b48Spatrick       // reported to the user.
126009467b48Spatrick       consumeError(Loc.takeError());
126109467b48Spatrick     }
126209467b48Spatrick 
126309467b48Spatrick     if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
126409467b48Spatrick       Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
126509467b48Spatrick 
126609467b48Spatrick     if (auto Origin =
126709467b48Spatrick             Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
126809467b48Spatrick       Die = Origin;
126909467b48Spatrick     if (auto NameAttr = Die.find(DW_AT_name))
1270*d415bd75Srobert       if (std::optional<const char *> Name = dwarf::toString(*NameAttr))
127109467b48Spatrick         Local.Name = *Name;
127209467b48Spatrick     if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
1273*d415bd75Srobert       Local.Size = Type.getTypeSize(getCUAddrSize());
127409467b48Spatrick     if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
127509467b48Spatrick       if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
127609467b48Spatrick         LT->getFileNameByIndex(
1277*d415bd75Srobert             *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),
127809467b48Spatrick             DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
127909467b48Spatrick             Local.DeclFile);
128009467b48Spatrick     }
128109467b48Spatrick     if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
1282*d415bd75Srobert       Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();
128309467b48Spatrick 
128409467b48Spatrick     Result.push_back(Local);
128509467b48Spatrick     return;
128609467b48Spatrick   }
128709467b48Spatrick 
128809467b48Spatrick   if (Die.getTag() == DW_TAG_inlined_subroutine)
128909467b48Spatrick     if (auto Origin =
129009467b48Spatrick             Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
129109467b48Spatrick       Subprogram = Origin;
129209467b48Spatrick 
129309467b48Spatrick   for (auto Child : Die)
129409467b48Spatrick     addLocalsForDie(CU, Subprogram, Child, Result);
129509467b48Spatrick }
129609467b48Spatrick 
129709467b48Spatrick std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address)129809467b48Spatrick DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
129909467b48Spatrick   std::vector<DILocal> Result;
130009467b48Spatrick   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
130109467b48Spatrick   if (!CU)
130209467b48Spatrick     return Result;
130309467b48Spatrick 
130409467b48Spatrick   DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
130509467b48Spatrick   if (Subprogram.isValid())
130609467b48Spatrick     addLocalsForDie(CU, Subprogram, Subprogram, Result);
130709467b48Spatrick   return Result;
130809467b48Spatrick }
130909467b48Spatrick 
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)131009467b48Spatrick DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
131109467b48Spatrick                                                DILineInfoSpecifier Spec) {
131209467b48Spatrick   DILineInfo Result;
131309467b48Spatrick   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
131409467b48Spatrick   if (!CU)
131509467b48Spatrick     return Result;
131609467b48Spatrick 
131773471bf0Spatrick   getFunctionNameAndStartLineForAddress(
131873471bf0Spatrick       CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,
131973471bf0Spatrick       Result.StartFileName, Result.StartLine, Result.StartAddress);
132009467b48Spatrick   if (Spec.FLIKind != FileLineInfoKind::None) {
132109467b48Spatrick     if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
132209467b48Spatrick       LineTable->getFileLineInfoForAddress(
132309467b48Spatrick           {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
132409467b48Spatrick           Spec.FLIKind, Result);
132509467b48Spatrick     }
132609467b48Spatrick   }
1327*d415bd75Srobert 
1328*d415bd75Srobert   return Result;
1329*d415bd75Srobert }
1330*d415bd75Srobert 
1331*d415bd75Srobert DILineInfo
getLineInfoForDataAddress(object::SectionedAddress Address)1332*d415bd75Srobert DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
1333*d415bd75Srobert   DILineInfo Result;
1334*d415bd75Srobert   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
1335*d415bd75Srobert   if (!CU)
1336*d415bd75Srobert     return Result;
1337*d415bd75Srobert 
1338*d415bd75Srobert   if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {
1339*d415bd75Srobert     Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);
1340*d415bd75Srobert     Result.Line = Die.getDeclLine();
1341*d415bd75Srobert   }
1342*d415bd75Srobert 
134309467b48Spatrick   return Result;
134409467b48Spatrick }
134509467b48Spatrick 
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Spec)134609467b48Spatrick DILineInfoTable DWARFContext::getLineInfoForAddressRange(
134709467b48Spatrick     object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
134809467b48Spatrick   DILineInfoTable Lines;
134909467b48Spatrick   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
135009467b48Spatrick   if (!CU)
135109467b48Spatrick     return Lines;
135209467b48Spatrick 
135309467b48Spatrick   uint32_t StartLine = 0;
135473471bf0Spatrick   std::string StartFileName;
135509467b48Spatrick   std::string FunctionName(DILineInfo::BadString);
1356*d415bd75Srobert   std::optional<uint64_t> StartAddress;
135709467b48Spatrick   getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
135873471bf0Spatrick                                         Spec.FLIKind, FunctionName,
135973471bf0Spatrick                                         StartFileName, StartLine, StartAddress);
136009467b48Spatrick 
136109467b48Spatrick   // If the Specifier says we don't need FileLineInfo, just
136209467b48Spatrick   // return the top-most function at the starting address.
136309467b48Spatrick   if (Spec.FLIKind == FileLineInfoKind::None) {
136409467b48Spatrick     DILineInfo Result;
136509467b48Spatrick     Result.FunctionName = FunctionName;
136673471bf0Spatrick     Result.StartFileName = StartFileName;
136709467b48Spatrick     Result.StartLine = StartLine;
136873471bf0Spatrick     Result.StartAddress = StartAddress;
136909467b48Spatrick     Lines.push_back(std::make_pair(Address.Address, Result));
137009467b48Spatrick     return Lines;
137109467b48Spatrick   }
137209467b48Spatrick 
137309467b48Spatrick   const DWARFLineTable *LineTable = getLineTableForUnit(CU);
137409467b48Spatrick 
137509467b48Spatrick   // Get the index of row we're looking for in the line table.
137609467b48Spatrick   std::vector<uint32_t> RowVector;
137709467b48Spatrick   if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
137809467b48Spatrick                                      Size, RowVector)) {
137909467b48Spatrick     return Lines;
138009467b48Spatrick   }
138109467b48Spatrick 
138209467b48Spatrick   for (uint32_t RowIndex : RowVector) {
138309467b48Spatrick     // Take file number and line/column from the row.
138409467b48Spatrick     const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
138509467b48Spatrick     DILineInfo Result;
138609467b48Spatrick     LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
138709467b48Spatrick                                   Spec.FLIKind, Result.FileName);
138809467b48Spatrick     Result.FunctionName = FunctionName;
138909467b48Spatrick     Result.Line = Row.Line;
139009467b48Spatrick     Result.Column = Row.Column;
139173471bf0Spatrick     Result.StartFileName = StartFileName;
139209467b48Spatrick     Result.StartLine = StartLine;
139373471bf0Spatrick     Result.StartAddress = StartAddress;
139409467b48Spatrick     Lines.push_back(std::make_pair(Row.Address.Address, Result));
139509467b48Spatrick   }
139609467b48Spatrick 
139709467b48Spatrick   return Lines;
139809467b48Spatrick }
139909467b48Spatrick 
140009467b48Spatrick DIInliningInfo
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)140109467b48Spatrick DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
140209467b48Spatrick                                         DILineInfoSpecifier Spec) {
140309467b48Spatrick   DIInliningInfo InliningInfo;
140409467b48Spatrick 
140509467b48Spatrick   DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
140609467b48Spatrick   if (!CU)
140709467b48Spatrick     return InliningInfo;
140809467b48Spatrick 
140909467b48Spatrick   const DWARFLineTable *LineTable = nullptr;
141009467b48Spatrick   SmallVector<DWARFDie, 4> InlinedChain;
141109467b48Spatrick   CU->getInlinedChainForAddress(Address.Address, InlinedChain);
141209467b48Spatrick   if (InlinedChain.size() == 0) {
141309467b48Spatrick     // If there is no DIE for address (e.g. it is in unavailable .dwo file),
141409467b48Spatrick     // try to at least get file/line info from symbol table.
141509467b48Spatrick     if (Spec.FLIKind != FileLineInfoKind::None) {
141609467b48Spatrick       DILineInfo Frame;
141709467b48Spatrick       LineTable = getLineTableForUnit(CU);
141809467b48Spatrick       if (LineTable && LineTable->getFileLineInfoForAddress(
141909467b48Spatrick                            {Address.Address, Address.SectionIndex},
142009467b48Spatrick                            CU->getCompilationDir(), Spec.FLIKind, Frame))
142109467b48Spatrick         InliningInfo.addFrame(Frame);
142209467b48Spatrick     }
142309467b48Spatrick     return InliningInfo;
142409467b48Spatrick   }
142509467b48Spatrick 
142609467b48Spatrick   uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;
142709467b48Spatrick   for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
142809467b48Spatrick     DWARFDie &FunctionDIE = InlinedChain[i];
142909467b48Spatrick     DILineInfo Frame;
143009467b48Spatrick     // Get function name if necessary.
143109467b48Spatrick     if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
143209467b48Spatrick       Frame.FunctionName = Name;
143309467b48Spatrick     if (auto DeclLineResult = FunctionDIE.getDeclLine())
143409467b48Spatrick       Frame.StartLine = DeclLineResult;
143573471bf0Spatrick     Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);
143673471bf0Spatrick     if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))
143773471bf0Spatrick       Frame.StartAddress = LowPcAddr->Address;
143809467b48Spatrick     if (Spec.FLIKind != FileLineInfoKind::None) {
143909467b48Spatrick       if (i == 0) {
144009467b48Spatrick         // For the topmost frame, initialize the line table of this
144109467b48Spatrick         // compile unit and fetch file/line info from it.
144209467b48Spatrick         LineTable = getLineTableForUnit(CU);
144309467b48Spatrick         // For the topmost routine, get file/line info from line table.
144409467b48Spatrick         if (LineTable)
144509467b48Spatrick           LineTable->getFileLineInfoForAddress(
144609467b48Spatrick               {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
144709467b48Spatrick               Spec.FLIKind, Frame);
144809467b48Spatrick       } else {
144909467b48Spatrick         // Otherwise, use call file, call line and call column from
145009467b48Spatrick         // previous DIE in inlined chain.
145109467b48Spatrick         if (LineTable)
145209467b48Spatrick           LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
145309467b48Spatrick                                         Spec.FLIKind, Frame.FileName);
145409467b48Spatrick         Frame.Line = CallLine;
145509467b48Spatrick         Frame.Column = CallColumn;
145609467b48Spatrick         Frame.Discriminator = CallDiscriminator;
145709467b48Spatrick       }
145809467b48Spatrick       // Get call file/line/column of a current DIE.
145909467b48Spatrick       if (i + 1 < n) {
146009467b48Spatrick         FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,
146109467b48Spatrick                                    CallDiscriminator);
146209467b48Spatrick       }
146309467b48Spatrick     }
146409467b48Spatrick     InliningInfo.addFrame(Frame);
146509467b48Spatrick   }
146609467b48Spatrick   return InliningInfo;
146709467b48Spatrick }
146809467b48Spatrick 
146909467b48Spatrick std::shared_ptr<DWARFContext>
getDWOContext(StringRef AbsolutePath)147009467b48Spatrick DWARFContext::getDWOContext(StringRef AbsolutePath) {
147109467b48Spatrick   if (auto S = DWP.lock()) {
147209467b48Spatrick     DWARFContext *Ctxt = S->Context.get();
147309467b48Spatrick     return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
147409467b48Spatrick   }
147509467b48Spatrick 
147609467b48Spatrick   std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
147709467b48Spatrick 
147809467b48Spatrick   if (auto S = Entry->lock()) {
147909467b48Spatrick     DWARFContext *Ctxt = S->Context.get();
148009467b48Spatrick     return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
148109467b48Spatrick   }
148209467b48Spatrick 
148309467b48Spatrick   Expected<OwningBinary<ObjectFile>> Obj = [&] {
148409467b48Spatrick     if (!CheckedForDWP) {
148509467b48Spatrick       SmallString<128> DWPName;
148609467b48Spatrick       auto Obj = object::ObjectFile::createObjectFile(
148709467b48Spatrick           this->DWPName.empty()
148809467b48Spatrick               ? (DObj->getFileName() + ".dwp").toStringRef(DWPName)
148909467b48Spatrick               : StringRef(this->DWPName));
149009467b48Spatrick       if (Obj) {
149109467b48Spatrick         Entry = &DWP;
149209467b48Spatrick         return Obj;
149309467b48Spatrick       } else {
149409467b48Spatrick         CheckedForDWP = true;
149509467b48Spatrick         // TODO: Should this error be handled (maybe in a high verbosity mode)
149609467b48Spatrick         // before falling back to .dwo files?
149709467b48Spatrick         consumeError(Obj.takeError());
149809467b48Spatrick       }
149909467b48Spatrick     }
150009467b48Spatrick 
150109467b48Spatrick     return object::ObjectFile::createObjectFile(AbsolutePath);
150209467b48Spatrick   }();
150309467b48Spatrick 
150409467b48Spatrick   if (!Obj) {
150509467b48Spatrick     // TODO: Actually report errors helpfully.
150609467b48Spatrick     consumeError(Obj.takeError());
150709467b48Spatrick     return nullptr;
150809467b48Spatrick   }
150909467b48Spatrick 
151009467b48Spatrick   auto S = std::make_shared<DWOFile>();
151109467b48Spatrick   S->File = std::move(Obj.get());
1512*d415bd75Srobert   S->Context = DWARFContext::create(*S->File.getBinary(),
1513*d415bd75Srobert                                     ProcessDebugRelocations::Ignore);
151409467b48Spatrick   *Entry = S;
151509467b48Spatrick   auto *Ctxt = S->Context.get();
151609467b48Spatrick   return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
151709467b48Spatrick }
151809467b48Spatrick 
createError(const Twine & Reason,llvm::Error E)151909467b48Spatrick static Error createError(const Twine &Reason, llvm::Error E) {
152009467b48Spatrick   return make_error<StringError>(Reason + toString(std::move(E)),
152109467b48Spatrick                                  inconvertibleErrorCode());
152209467b48Spatrick }
152309467b48Spatrick 
152409467b48Spatrick /// SymInfo contains information about symbol: it's address
152509467b48Spatrick /// and section index which is -1LL for absolute symbols.
152609467b48Spatrick struct SymInfo {
152709467b48Spatrick   uint64_t Address;
152809467b48Spatrick   uint64_t SectionIndex;
152909467b48Spatrick };
153009467b48Spatrick 
153109467b48Spatrick /// Returns the address of symbol relocation used against and a section index.
153209467b48Spatrick /// 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)153309467b48Spatrick static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
153409467b48Spatrick                                        const RelocationRef &Reloc,
153509467b48Spatrick                                        const LoadedObjectInfo *L,
153609467b48Spatrick                                        std::map<SymbolRef, SymInfo> &Cache) {
153709467b48Spatrick   SymInfo Ret = {0, (uint64_t)-1LL};
153809467b48Spatrick   object::section_iterator RSec = Obj.section_end();
153909467b48Spatrick   object::symbol_iterator Sym = Reloc.getSymbol();
154009467b48Spatrick 
154109467b48Spatrick   std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
154209467b48Spatrick   // First calculate the address of the symbol or section as it appears
154309467b48Spatrick   // in the object file
154409467b48Spatrick   if (Sym != Obj.symbol_end()) {
154509467b48Spatrick     bool New;
154609467b48Spatrick     std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});
154709467b48Spatrick     if (!New)
154809467b48Spatrick       return CacheIt->second;
154909467b48Spatrick 
155009467b48Spatrick     Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
155109467b48Spatrick     if (!SymAddrOrErr)
155209467b48Spatrick       return createError("failed to compute symbol address: ",
155309467b48Spatrick                          SymAddrOrErr.takeError());
155409467b48Spatrick 
155509467b48Spatrick     // Also remember what section this symbol is in for later
155609467b48Spatrick     auto SectOrErr = Sym->getSection();
155709467b48Spatrick     if (!SectOrErr)
155809467b48Spatrick       return createError("failed to get symbol section: ",
155909467b48Spatrick                          SectOrErr.takeError());
156009467b48Spatrick 
156109467b48Spatrick     RSec = *SectOrErr;
156209467b48Spatrick     Ret.Address = *SymAddrOrErr;
156309467b48Spatrick   } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
156409467b48Spatrick     RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
156509467b48Spatrick     Ret.Address = RSec->getAddress();
156609467b48Spatrick   }
156709467b48Spatrick 
156809467b48Spatrick   if (RSec != Obj.section_end())
156909467b48Spatrick     Ret.SectionIndex = RSec->getIndex();
157009467b48Spatrick 
157109467b48Spatrick   // If we are given load addresses for the sections, we need to adjust:
157209467b48Spatrick   // SymAddr = (Address of Symbol Or Section in File) -
157309467b48Spatrick   //           (Address of Section in File) +
157409467b48Spatrick   //           (Load Address of Section)
157509467b48Spatrick   // RSec is now either the section being targeted or the section
157609467b48Spatrick   // containing the symbol being targeted. In either case,
157709467b48Spatrick   // we need to perform the same computation.
157809467b48Spatrick   if (L && RSec != Obj.section_end())
157909467b48Spatrick     if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
158009467b48Spatrick       Ret.Address += SectionLoadAddress - RSec->getAddress();
158109467b48Spatrick 
158209467b48Spatrick   if (CacheIt != Cache.end())
158309467b48Spatrick     CacheIt->second = Ret;
158409467b48Spatrick 
158509467b48Spatrick   return Ret;
158609467b48Spatrick }
158709467b48Spatrick 
isRelocScattered(const object::ObjectFile & Obj,const RelocationRef & Reloc)158809467b48Spatrick static bool isRelocScattered(const object::ObjectFile &Obj,
158909467b48Spatrick                              const RelocationRef &Reloc) {
159009467b48Spatrick   const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
159109467b48Spatrick   if (!MachObj)
159209467b48Spatrick     return false;
159309467b48Spatrick   // MachO also has relocations that point to sections and
159409467b48Spatrick   // scattered relocations.
159509467b48Spatrick   auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
159609467b48Spatrick   return MachObj->isRelocationScattered(RelocInfo);
159709467b48Spatrick }
159809467b48Spatrick 
159909467b48Spatrick namespace {
160009467b48Spatrick struct DWARFSectionMap final : public DWARFSection {
160109467b48Spatrick   RelocAddrMap Relocs;
160209467b48Spatrick };
160309467b48Spatrick 
160409467b48Spatrick class DWARFObjInMemory final : public DWARFObject {
160509467b48Spatrick   bool IsLittleEndian;
160609467b48Spatrick   uint8_t AddressSize;
160709467b48Spatrick   StringRef FileName;
160809467b48Spatrick   const object::ObjectFile *Obj = nullptr;
160909467b48Spatrick   std::vector<SectionName> SectionNames;
161009467b48Spatrick 
161109467b48Spatrick   using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,
161209467b48Spatrick                                    std::map<object::SectionRef, unsigned>>;
161309467b48Spatrick 
161409467b48Spatrick   InfoSectionMap InfoSections;
161509467b48Spatrick   InfoSectionMap TypesSections;
161609467b48Spatrick   InfoSectionMap InfoDWOSections;
161709467b48Spatrick   InfoSectionMap TypesDWOSections;
161809467b48Spatrick 
161909467b48Spatrick   DWARFSectionMap LocSection;
162009467b48Spatrick   DWARFSectionMap LoclistsSection;
162109467b48Spatrick   DWARFSectionMap LoclistsDWOSection;
162209467b48Spatrick   DWARFSectionMap LineSection;
162309467b48Spatrick   DWARFSectionMap RangesSection;
162409467b48Spatrick   DWARFSectionMap RnglistsSection;
162509467b48Spatrick   DWARFSectionMap StrOffsetsSection;
162609467b48Spatrick   DWARFSectionMap LineDWOSection;
162709467b48Spatrick   DWARFSectionMap FrameSection;
162809467b48Spatrick   DWARFSectionMap EHFrameSection;
162909467b48Spatrick   DWARFSectionMap LocDWOSection;
163009467b48Spatrick   DWARFSectionMap StrOffsetsDWOSection;
163109467b48Spatrick   DWARFSectionMap RangesDWOSection;
163209467b48Spatrick   DWARFSectionMap RnglistsDWOSection;
163309467b48Spatrick   DWARFSectionMap AddrSection;
163409467b48Spatrick   DWARFSectionMap AppleNamesSection;
163509467b48Spatrick   DWARFSectionMap AppleTypesSection;
163609467b48Spatrick   DWARFSectionMap AppleNamespacesSection;
163709467b48Spatrick   DWARFSectionMap AppleObjCSection;
163809467b48Spatrick   DWARFSectionMap NamesSection;
163909467b48Spatrick   DWARFSectionMap PubnamesSection;
164009467b48Spatrick   DWARFSectionMap PubtypesSection;
164109467b48Spatrick   DWARFSectionMap GnuPubnamesSection;
164209467b48Spatrick   DWARFSectionMap GnuPubtypesSection;
1643097a140dSpatrick   DWARFSectionMap MacroSection;
164409467b48Spatrick 
mapNameToDWARFSection(StringRef Name)164509467b48Spatrick   DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {
164609467b48Spatrick     return StringSwitch<DWARFSectionMap *>(Name)
164709467b48Spatrick         .Case("debug_loc", &LocSection)
164809467b48Spatrick         .Case("debug_loclists", &LoclistsSection)
164909467b48Spatrick         .Case("debug_loclists.dwo", &LoclistsDWOSection)
165009467b48Spatrick         .Case("debug_line", &LineSection)
165109467b48Spatrick         .Case("debug_frame", &FrameSection)
165209467b48Spatrick         .Case("eh_frame", &EHFrameSection)
165309467b48Spatrick         .Case("debug_str_offsets", &StrOffsetsSection)
165409467b48Spatrick         .Case("debug_ranges", &RangesSection)
165509467b48Spatrick         .Case("debug_rnglists", &RnglistsSection)
165609467b48Spatrick         .Case("debug_loc.dwo", &LocDWOSection)
165709467b48Spatrick         .Case("debug_line.dwo", &LineDWOSection)
165809467b48Spatrick         .Case("debug_names", &NamesSection)
165909467b48Spatrick         .Case("debug_rnglists.dwo", &RnglistsDWOSection)
166009467b48Spatrick         .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)
166109467b48Spatrick         .Case("debug_addr", &AddrSection)
166209467b48Spatrick         .Case("apple_names", &AppleNamesSection)
166309467b48Spatrick         .Case("debug_pubnames", &PubnamesSection)
166409467b48Spatrick         .Case("debug_pubtypes", &PubtypesSection)
166509467b48Spatrick         .Case("debug_gnu_pubnames", &GnuPubnamesSection)
166609467b48Spatrick         .Case("debug_gnu_pubtypes", &GnuPubtypesSection)
166709467b48Spatrick         .Case("apple_types", &AppleTypesSection)
166809467b48Spatrick         .Case("apple_namespaces", &AppleNamespacesSection)
166909467b48Spatrick         .Case("apple_namespac", &AppleNamespacesSection)
167009467b48Spatrick         .Case("apple_objc", &AppleObjCSection)
1671097a140dSpatrick         .Case("debug_macro", &MacroSection)
167209467b48Spatrick         .Default(nullptr);
167309467b48Spatrick   }
167409467b48Spatrick 
167509467b48Spatrick   StringRef AbbrevSection;
167609467b48Spatrick   StringRef ArangesSection;
167709467b48Spatrick   StringRef StrSection;
167809467b48Spatrick   StringRef MacinfoSection;
167909467b48Spatrick   StringRef MacinfoDWOSection;
1680097a140dSpatrick   StringRef MacroDWOSection;
168109467b48Spatrick   StringRef AbbrevDWOSection;
168209467b48Spatrick   StringRef StrDWOSection;
168309467b48Spatrick   StringRef CUIndexSection;
168409467b48Spatrick   StringRef GdbIndexSection;
168509467b48Spatrick   StringRef TUIndexSection;
168609467b48Spatrick   StringRef LineStrSection;
168709467b48Spatrick 
168809467b48Spatrick   // A deque holding section data whose iterators are not invalidated when
168909467b48Spatrick   // new decompressed sections are inserted at the end.
169009467b48Spatrick   std::deque<SmallString<0>> UncompressedSections;
169109467b48Spatrick 
mapSectionToMember(StringRef Name)169209467b48Spatrick   StringRef *mapSectionToMember(StringRef Name) {
169309467b48Spatrick     if (DWARFSection *Sec = mapNameToDWARFSection(Name))
169409467b48Spatrick       return &Sec->Data;
169509467b48Spatrick     return StringSwitch<StringRef *>(Name)
169609467b48Spatrick         .Case("debug_abbrev", &AbbrevSection)
169709467b48Spatrick         .Case("debug_aranges", &ArangesSection)
169809467b48Spatrick         .Case("debug_str", &StrSection)
169909467b48Spatrick         .Case("debug_macinfo", &MacinfoSection)
170009467b48Spatrick         .Case("debug_macinfo.dwo", &MacinfoDWOSection)
1701097a140dSpatrick         .Case("debug_macro.dwo", &MacroDWOSection)
170209467b48Spatrick         .Case("debug_abbrev.dwo", &AbbrevDWOSection)
170309467b48Spatrick         .Case("debug_str.dwo", &StrDWOSection)
170409467b48Spatrick         .Case("debug_cu_index", &CUIndexSection)
170509467b48Spatrick         .Case("debug_tu_index", &TUIndexSection)
170609467b48Spatrick         .Case("gdb_index", &GdbIndexSection)
170709467b48Spatrick         .Case("debug_line_str", &LineStrSection)
170809467b48Spatrick         // Any more debug info sections go here.
170909467b48Spatrick         .Default(nullptr);
171009467b48Spatrick   }
171109467b48Spatrick 
171209467b48Spatrick   /// If Sec is compressed section, decompresses and updates its contents
171309467b48Spatrick   /// provided by Data. Otherwise leaves it unchanged.
maybeDecompress(const object::SectionRef & Sec,StringRef Name,StringRef & Data)171409467b48Spatrick   Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
171509467b48Spatrick                         StringRef &Data) {
1716*d415bd75Srobert     if (!Sec.isCompressed())
171709467b48Spatrick       return Error::success();
171809467b48Spatrick 
171909467b48Spatrick     Expected<Decompressor> Decompressor =
172009467b48Spatrick         Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);
172109467b48Spatrick     if (!Decompressor)
172209467b48Spatrick       return Decompressor.takeError();
172309467b48Spatrick 
172409467b48Spatrick     SmallString<0> Out;
172509467b48Spatrick     if (auto Err = Decompressor->resizeAndDecompress(Out))
172609467b48Spatrick       return Err;
172709467b48Spatrick 
172809467b48Spatrick     UncompressedSections.push_back(std::move(Out));
172909467b48Spatrick     Data = UncompressedSections.back();
173009467b48Spatrick 
173109467b48Spatrick     return Error::success();
173209467b48Spatrick   }
173309467b48Spatrick 
173409467b48Spatrick public:
DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool IsLittleEndian)173509467b48Spatrick   DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
173609467b48Spatrick                    uint8_t AddrSize, bool IsLittleEndian)
173709467b48Spatrick       : IsLittleEndian(IsLittleEndian) {
173809467b48Spatrick     for (const auto &SecIt : Sections) {
173909467b48Spatrick       if (StringRef *SectionData = mapSectionToMember(SecIt.first()))
174009467b48Spatrick         *SectionData = SecIt.second->getBuffer();
174109467b48Spatrick       else if (SecIt.first() == "debug_info")
174209467b48Spatrick         // Find debug_info and debug_types data by section rather than name as
174309467b48Spatrick         // there are multiple, comdat grouped, of these sections.
174409467b48Spatrick         InfoSections[SectionRef()].Data = SecIt.second->getBuffer();
174509467b48Spatrick       else if (SecIt.first() == "debug_info.dwo")
174609467b48Spatrick         InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
174709467b48Spatrick       else if (SecIt.first() == "debug_types")
174809467b48Spatrick         TypesSections[SectionRef()].Data = SecIt.second->getBuffer();
174909467b48Spatrick       else if (SecIt.first() == "debug_types.dwo")
175009467b48Spatrick         TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();
175109467b48Spatrick     }
175209467b48Spatrick   }
DWARFObjInMemory(const object::ObjectFile & Obj,const LoadedObjectInfo * L,function_ref<void (Error)> HandleError,function_ref<void (Error)> HandleWarning,DWARFContext::ProcessDebugRelocations RelocAction)175309467b48Spatrick   DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,
1754*d415bd75Srobert                    function_ref<void(Error)> HandleError,
1755*d415bd75Srobert                    function_ref<void(Error)> HandleWarning,
1756*d415bd75Srobert                    DWARFContext::ProcessDebugRelocations RelocAction)
175709467b48Spatrick       : IsLittleEndian(Obj.isLittleEndian()),
175809467b48Spatrick         AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),
175909467b48Spatrick         Obj(&Obj) {
176009467b48Spatrick 
176109467b48Spatrick     StringMap<unsigned> SectionAmountMap;
176209467b48Spatrick     for (const SectionRef &Section : Obj.sections()) {
176309467b48Spatrick       StringRef Name;
176409467b48Spatrick       if (auto NameOrErr = Section.getName())
176509467b48Spatrick         Name = *NameOrErr;
176609467b48Spatrick       else
176709467b48Spatrick         consumeError(NameOrErr.takeError());
176809467b48Spatrick 
176909467b48Spatrick       ++SectionAmountMap[Name];
177009467b48Spatrick       SectionNames.push_back({ Name, true });
177109467b48Spatrick 
177209467b48Spatrick       // Skip BSS and Virtual sections, they aren't interesting.
177309467b48Spatrick       if (Section.isBSS() || Section.isVirtual())
177409467b48Spatrick         continue;
177509467b48Spatrick 
177609467b48Spatrick       // Skip sections stripped by dsymutil.
177709467b48Spatrick       if (Section.isStripped())
177809467b48Spatrick         continue;
177909467b48Spatrick 
178009467b48Spatrick       StringRef Data;
178109467b48Spatrick       Expected<section_iterator> SecOrErr = Section.getRelocatedSection();
178209467b48Spatrick       if (!SecOrErr) {
1783097a140dSpatrick         HandleError(createError("failed to get relocated section: ",
1784097a140dSpatrick                                 SecOrErr.takeError()));
178509467b48Spatrick         continue;
178609467b48Spatrick       }
178709467b48Spatrick 
178809467b48Spatrick       // Try to obtain an already relocated version of this section.
178909467b48Spatrick       // Else use the unrelocated section from the object file. We'll have to
179009467b48Spatrick       // apply relocations ourselves later.
179173471bf0Spatrick       section_iterator RelocatedSection =
179273471bf0Spatrick           Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();
179309467b48Spatrick       if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
179409467b48Spatrick         Expected<StringRef> E = Section.getContents();
179509467b48Spatrick         if (E)
179609467b48Spatrick           Data = *E;
179709467b48Spatrick         else
179809467b48Spatrick           // maybeDecompress below will error.
179909467b48Spatrick           consumeError(E.takeError());
180009467b48Spatrick       }
180109467b48Spatrick 
180209467b48Spatrick       if (auto Err = maybeDecompress(Section, Name, Data)) {
1803097a140dSpatrick         HandleError(createError("failed to decompress '" + Name + "', ",
1804097a140dSpatrick                                 std::move(Err)));
180509467b48Spatrick         continue;
180609467b48Spatrick       }
180709467b48Spatrick 
180809467b48Spatrick       // Compressed sections names in GNU style starts from ".z",
180909467b48Spatrick       // at this point section is decompressed and we drop compression prefix.
181009467b48Spatrick       Name = Name.substr(
181109467b48Spatrick           Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
181209467b48Spatrick 
181309467b48Spatrick       // Map platform specific debug section names to DWARF standard section
181409467b48Spatrick       // names.
181509467b48Spatrick       Name = Obj.mapDebugSectionName(Name);
181609467b48Spatrick 
181709467b48Spatrick       if (StringRef *SectionData = mapSectionToMember(Name)) {
181809467b48Spatrick         *SectionData = Data;
181909467b48Spatrick         if (Name == "debug_ranges") {
182009467b48Spatrick           // FIXME: Use the other dwo range section when we emit it.
182109467b48Spatrick           RangesDWOSection.Data = Data;
182273471bf0Spatrick         } else if (Name == "debug_frame" || Name == "eh_frame") {
182373471bf0Spatrick           if (DWARFSection *S = mapNameToDWARFSection(Name))
182473471bf0Spatrick             S->Address = Section.getAddress();
182509467b48Spatrick         }
182673471bf0Spatrick       } else if (InfoSectionMap *Sections =
182773471bf0Spatrick                      StringSwitch<InfoSectionMap *>(Name)
182873471bf0Spatrick                          .Case("debug_info", &InfoSections)
182973471bf0Spatrick                          .Case("debug_info.dwo", &InfoDWOSections)
183073471bf0Spatrick                          .Case("debug_types", &TypesSections)
183173471bf0Spatrick                          .Case("debug_types.dwo", &TypesDWOSections)
183273471bf0Spatrick                          .Default(nullptr)) {
183309467b48Spatrick         // Find debug_info and debug_types data by section rather than name as
183409467b48Spatrick         // there are multiple, comdat grouped, of these sections.
183573471bf0Spatrick         DWARFSectionMap &S = (*Sections)[Section];
183673471bf0Spatrick         S.Data = Data;
183709467b48Spatrick       }
183809467b48Spatrick 
1839*d415bd75Srobert       if (RelocatedSection != Obj.section_end() && Name.contains(".dwo"))
1840*d415bd75Srobert         HandleWarning(
1841*d415bd75Srobert             createError("Unexpected relocations for dwo section " + Name));
1842*d415bd75Srobert 
1843*d415bd75Srobert       if (RelocatedSection == Obj.section_end() ||
1844*d415bd75Srobert           (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))
184509467b48Spatrick         continue;
184609467b48Spatrick 
184709467b48Spatrick       StringRef RelSecName;
184809467b48Spatrick       if (auto NameOrErr = RelocatedSection->getName())
184909467b48Spatrick         RelSecName = *NameOrErr;
185009467b48Spatrick       else
185109467b48Spatrick         consumeError(NameOrErr.takeError());
185209467b48Spatrick 
185309467b48Spatrick       // If the section we're relocating was relocated already by the JIT,
185409467b48Spatrick       // then we used the relocated version above, so we do not need to process
185509467b48Spatrick       // relocations for it now.
185609467b48Spatrick       StringRef RelSecData;
185709467b48Spatrick       if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
185809467b48Spatrick         continue;
185909467b48Spatrick 
186009467b48Spatrick       // In Mach-o files, the relocations do not need to be applied if
186109467b48Spatrick       // there is no load offset to apply. The value read at the
186209467b48Spatrick       // relocation point already factors in the section address
186309467b48Spatrick       // (actually applying the relocations will produce wrong results
186409467b48Spatrick       // as the section address will be added twice).
186509467b48Spatrick       if (!L && isa<MachOObjectFile>(&Obj))
186609467b48Spatrick         continue;
186709467b48Spatrick 
186809467b48Spatrick       RelSecName = RelSecName.substr(
186909467b48Spatrick           RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
187009467b48Spatrick 
187109467b48Spatrick       // TODO: Add support for relocations in other sections as needed.
187209467b48Spatrick       // Record relocations for the debug_info and debug_line sections.
187309467b48Spatrick       DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);
187409467b48Spatrick       RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;
187509467b48Spatrick       if (!Map) {
187609467b48Spatrick         // Find debug_info and debug_types relocs by section rather than name
187709467b48Spatrick         // as there are multiple, comdat grouped, of these sections.
187809467b48Spatrick         if (RelSecName == "debug_info")
187909467b48Spatrick           Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])
188009467b48Spatrick                      .Relocs;
188109467b48Spatrick         else if (RelSecName == "debug_types")
188209467b48Spatrick           Map =
188309467b48Spatrick               &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])
188409467b48Spatrick                    .Relocs;
188509467b48Spatrick         else
188609467b48Spatrick           continue;
188709467b48Spatrick       }
188809467b48Spatrick 
188909467b48Spatrick       if (Section.relocation_begin() == Section.relocation_end())
189009467b48Spatrick         continue;
189109467b48Spatrick 
189209467b48Spatrick       // Symbol to [address, section index] cache mapping.
189309467b48Spatrick       std::map<SymbolRef, SymInfo> AddrCache;
189473471bf0Spatrick       SupportsRelocation Supports;
189509467b48Spatrick       RelocationResolver Resolver;
189609467b48Spatrick       std::tie(Supports, Resolver) = getRelocationResolver(Obj);
189709467b48Spatrick       for (const RelocationRef &Reloc : Section.relocations()) {
189809467b48Spatrick         // FIXME: it's not clear how to correctly handle scattered
189909467b48Spatrick         // relocations.
190009467b48Spatrick         if (isRelocScattered(Obj, Reloc))
190109467b48Spatrick           continue;
190209467b48Spatrick 
190309467b48Spatrick         Expected<SymInfo> SymInfoOrErr =
190409467b48Spatrick             getSymbolInfo(Obj, Reloc, L, AddrCache);
190509467b48Spatrick         if (!SymInfoOrErr) {
1906097a140dSpatrick           HandleError(SymInfoOrErr.takeError());
190709467b48Spatrick           continue;
190809467b48Spatrick         }
190909467b48Spatrick 
191009467b48Spatrick         // Check if Resolver can handle this relocation type early so as not to
191109467b48Spatrick         // handle invalid cases in DWARFDataExtractor.
191209467b48Spatrick         //
191309467b48Spatrick         // TODO Don't store Resolver in every RelocAddrEntry.
191409467b48Spatrick         if (Supports && Supports(Reloc.getType())) {
191509467b48Spatrick           auto I = Map->try_emplace(
191609467b48Spatrick               Reloc.getOffset(),
1917*d415bd75Srobert               RelocAddrEntry{
1918*d415bd75Srobert                   SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,
1919*d415bd75Srobert                   std::optional<object::RelocationRef>(), 0, Resolver});
192009467b48Spatrick           // If we didn't successfully insert that's because we already had a
192109467b48Spatrick           // relocation for that offset. Store it as a second relocation in the
192209467b48Spatrick           // same RelocAddrEntry instead.
192309467b48Spatrick           if (!I.second) {
192409467b48Spatrick             RelocAddrEntry &entry = I.first->getSecond();
192509467b48Spatrick             if (entry.Reloc2) {
1926097a140dSpatrick               HandleError(createError(
192709467b48Spatrick                   "At most two relocations per offset are supported"));
192809467b48Spatrick             }
192909467b48Spatrick             entry.Reloc2 = Reloc;
193009467b48Spatrick             entry.SymbolValue2 = SymInfoOrErr->Address;
193109467b48Spatrick           }
193209467b48Spatrick         } else {
193309467b48Spatrick           SmallString<32> Type;
193409467b48Spatrick           Reloc.getTypeName(Type);
1935097a140dSpatrick           // FIXME: Support more relocations & change this to an error
1936097a140dSpatrick           HandleWarning(
193709467b48Spatrick               createError("failed to compute relocation: " + Type + ", ",
193809467b48Spatrick                           errorCodeToError(object_error::parse_failed)));
193909467b48Spatrick         }
194009467b48Spatrick       }
194109467b48Spatrick     }
194209467b48Spatrick 
194309467b48Spatrick     for (SectionName &S : SectionNames)
194409467b48Spatrick       if (SectionAmountMap[S.Name] > 1)
194509467b48Spatrick         S.IsNameUnique = false;
194609467b48Spatrick   }
194709467b48Spatrick 
find(const DWARFSection & S,uint64_t Pos) const1948*d415bd75Srobert   std::optional<RelocAddrEntry> find(const DWARFSection &S,
194909467b48Spatrick                                      uint64_t Pos) const override {
195009467b48Spatrick     auto &Sec = static_cast<const DWARFSectionMap &>(S);
195109467b48Spatrick     RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);
195209467b48Spatrick     if (AI == Sec.Relocs.end())
1953*d415bd75Srobert       return std::nullopt;
195409467b48Spatrick     return AI->second;
195509467b48Spatrick   }
195609467b48Spatrick 
getFile() const195709467b48Spatrick   const object::ObjectFile *getFile() const override { return Obj; }
195809467b48Spatrick 
getSectionNames() const195909467b48Spatrick   ArrayRef<SectionName> getSectionNames() const override {
196009467b48Spatrick     return SectionNames;
196109467b48Spatrick   }
196209467b48Spatrick 
isLittleEndian() const196309467b48Spatrick   bool isLittleEndian() const override { return IsLittleEndian; }
getAbbrevDWOSection() const196409467b48Spatrick   StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
getLineDWOSection() const196509467b48Spatrick   const DWARFSection &getLineDWOSection() const override {
196609467b48Spatrick     return LineDWOSection;
196709467b48Spatrick   }
getLocDWOSection() const196809467b48Spatrick   const DWARFSection &getLocDWOSection() const override {
196909467b48Spatrick     return LocDWOSection;
197009467b48Spatrick   }
getStrDWOSection() const197109467b48Spatrick   StringRef getStrDWOSection() const override { return StrDWOSection; }
getStrOffsetsDWOSection() const197209467b48Spatrick   const DWARFSection &getStrOffsetsDWOSection() const override {
197309467b48Spatrick     return StrOffsetsDWOSection;
197409467b48Spatrick   }
getRangesDWOSection() const197509467b48Spatrick   const DWARFSection &getRangesDWOSection() const override {
197609467b48Spatrick     return RangesDWOSection;
197709467b48Spatrick   }
getRnglistsDWOSection() const197809467b48Spatrick   const DWARFSection &getRnglistsDWOSection() const override {
197909467b48Spatrick     return RnglistsDWOSection;
198009467b48Spatrick   }
getLoclistsDWOSection() const198109467b48Spatrick   const DWARFSection &getLoclistsDWOSection() const override {
198209467b48Spatrick     return LoclistsDWOSection;
198309467b48Spatrick   }
getAddrSection() const198409467b48Spatrick   const DWARFSection &getAddrSection() const override { return AddrSection; }
getCUIndexSection() const198509467b48Spatrick   StringRef getCUIndexSection() const override { return CUIndexSection; }
getGdbIndexSection() const198609467b48Spatrick   StringRef getGdbIndexSection() const override { return GdbIndexSection; }
getTUIndexSection() const198709467b48Spatrick   StringRef getTUIndexSection() const override { return TUIndexSection; }
198809467b48Spatrick 
198909467b48Spatrick   // DWARF v5
getStrOffsetsSection() const199009467b48Spatrick   const DWARFSection &getStrOffsetsSection() const override {
199109467b48Spatrick     return StrOffsetsSection;
199209467b48Spatrick   }
getLineStrSection() const199309467b48Spatrick   StringRef getLineStrSection() const override { return LineStrSection; }
199409467b48Spatrick 
199509467b48Spatrick   // Sections for DWARF5 split dwarf proposal.
forEachInfoDWOSections(function_ref<void (const DWARFSection &)> F) const199609467b48Spatrick   void forEachInfoDWOSections(
199709467b48Spatrick       function_ref<void(const DWARFSection &)> F) const override {
199809467b48Spatrick     for (auto &P : InfoDWOSections)
199909467b48Spatrick       F(P.second);
200009467b48Spatrick   }
forEachTypesDWOSections(function_ref<void (const DWARFSection &)> F) const200109467b48Spatrick   void forEachTypesDWOSections(
200209467b48Spatrick       function_ref<void(const DWARFSection &)> F) const override {
200309467b48Spatrick     for (auto &P : TypesDWOSections)
200409467b48Spatrick       F(P.second);
200509467b48Spatrick   }
200609467b48Spatrick 
getAbbrevSection() const200709467b48Spatrick   StringRef getAbbrevSection() const override { return AbbrevSection; }
getLocSection() const200809467b48Spatrick   const DWARFSection &getLocSection() const override { return LocSection; }
getLoclistsSection() const200909467b48Spatrick   const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
getArangesSection() const201009467b48Spatrick   StringRef getArangesSection() const override { return ArangesSection; }
getFrameSection() const201109467b48Spatrick   const DWARFSection &getFrameSection() const override {
201209467b48Spatrick     return FrameSection;
201309467b48Spatrick   }
getEHFrameSection() const201409467b48Spatrick   const DWARFSection &getEHFrameSection() const override {
201509467b48Spatrick     return EHFrameSection;
201609467b48Spatrick   }
getLineSection() const201709467b48Spatrick   const DWARFSection &getLineSection() const override { return LineSection; }
getStrSection() const201809467b48Spatrick   StringRef getStrSection() const override { return StrSection; }
getRangesSection() const201909467b48Spatrick   const DWARFSection &getRangesSection() const override { return RangesSection; }
getRnglistsSection() const202009467b48Spatrick   const DWARFSection &getRnglistsSection() const override {
202109467b48Spatrick     return RnglistsSection;
202209467b48Spatrick   }
getMacroSection() const2023097a140dSpatrick   const DWARFSection &getMacroSection() const override { return MacroSection; }
getMacroDWOSection() const2024097a140dSpatrick   StringRef getMacroDWOSection() const override { return MacroDWOSection; }
getMacinfoSection() const202509467b48Spatrick   StringRef getMacinfoSection() const override { return MacinfoSection; }
getMacinfoDWOSection() const202609467b48Spatrick   StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
getPubnamesSection() const202709467b48Spatrick   const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
getPubtypesSection() const202809467b48Spatrick   const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
getGnuPubnamesSection() const202909467b48Spatrick   const DWARFSection &getGnuPubnamesSection() const override {
203009467b48Spatrick     return GnuPubnamesSection;
203109467b48Spatrick   }
getGnuPubtypesSection() const203209467b48Spatrick   const DWARFSection &getGnuPubtypesSection() const override {
203309467b48Spatrick     return GnuPubtypesSection;
203409467b48Spatrick   }
getAppleNamesSection() const203509467b48Spatrick   const DWARFSection &getAppleNamesSection() const override {
203609467b48Spatrick     return AppleNamesSection;
203709467b48Spatrick   }
getAppleTypesSection() const203809467b48Spatrick   const DWARFSection &getAppleTypesSection() const override {
203909467b48Spatrick     return AppleTypesSection;
204009467b48Spatrick   }
getAppleNamespacesSection() const204109467b48Spatrick   const DWARFSection &getAppleNamespacesSection() const override {
204209467b48Spatrick     return AppleNamespacesSection;
204309467b48Spatrick   }
getAppleObjCSection() const204409467b48Spatrick   const DWARFSection &getAppleObjCSection() const override {
204509467b48Spatrick     return AppleObjCSection;
204609467b48Spatrick   }
getNamesSection() const204709467b48Spatrick   const DWARFSection &getNamesSection() const override {
204809467b48Spatrick     return NamesSection;
204909467b48Spatrick   }
205009467b48Spatrick 
getFileName() const205109467b48Spatrick   StringRef getFileName() const override { return FileName; }
getAddressSize() const205209467b48Spatrick   uint8_t getAddressSize() const override { return AddressSize; }
forEachInfoSections(function_ref<void (const DWARFSection &)> F) const205309467b48Spatrick   void forEachInfoSections(
205409467b48Spatrick       function_ref<void(const DWARFSection &)> F) const override {
205509467b48Spatrick     for (auto &P : InfoSections)
205609467b48Spatrick       F(P.second);
205709467b48Spatrick   }
forEachTypesSections(function_ref<void (const DWARFSection &)> F) const205809467b48Spatrick   void forEachTypesSections(
205909467b48Spatrick       function_ref<void(const DWARFSection &)> F) const override {
206009467b48Spatrick     for (auto &P : TypesSections)
206109467b48Spatrick       F(P.second);
206209467b48Spatrick   }
206309467b48Spatrick };
206409467b48Spatrick } // namespace
206509467b48Spatrick 
206609467b48Spatrick 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)2067*d415bd75Srobert DWARFContext::create(const object::ObjectFile &Obj,
2068*d415bd75Srobert                      ProcessDebugRelocations RelocAction,
2069*d415bd75Srobert                      const LoadedObjectInfo *L, std::string DWPName,
2070097a140dSpatrick                      std::function<void(Error)> RecoverableErrorHandler,
2071097a140dSpatrick                      std::function<void(Error)> WarningHandler) {
2072*d415bd75Srobert   auto DObj = std::make_unique<DWARFObjInMemory>(
2073*d415bd75Srobert       Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);
2074097a140dSpatrick   return std::make_unique<DWARFContext>(std::move(DObj), std::move(DWPName),
2075097a140dSpatrick                                         RecoverableErrorHandler,
2076097a140dSpatrick                                         WarningHandler);
207709467b48Spatrick }
207809467b48Spatrick 
207909467b48Spatrick 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)208009467b48Spatrick DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
2081097a140dSpatrick                      uint8_t AddrSize, bool isLittleEndian,
2082097a140dSpatrick                      std::function<void(Error)> RecoverableErrorHandler,
2083097a140dSpatrick                      std::function<void(Error)> WarningHandler) {
208409467b48Spatrick   auto DObj =
208509467b48Spatrick       std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
2086097a140dSpatrick   return std::make_unique<DWARFContext>(
2087097a140dSpatrick       std::move(DObj), "", RecoverableErrorHandler, WarningHandler);
208809467b48Spatrick }
208909467b48Spatrick 
getCUAddrSize()209009467b48Spatrick uint8_t DWARFContext::getCUAddrSize() {
209109467b48Spatrick   // In theory, different compile units may have different address byte
209209467b48Spatrick   // sizes, but for simplicity we just use the address byte size of the
2093097a140dSpatrick   // first compile unit. In practice the address size field is repeated across
209409467b48Spatrick   // various DWARF headers (at least in version 5) to make it easier to dump
209509467b48Spatrick   // them independently, not to enable varying the address size.
209673471bf0Spatrick   auto CUs = compile_units();
2097097a140dSpatrick   return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();
209809467b48Spatrick }
2099