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 *>> ⤅
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