10b57cec5SDimitry Andric //===- DWARFContext.cpp ---------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 1081ad6265SDimitry Andric #include "llvm/ADT/MapVector.h" 110b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 120b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 130b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 150b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 160b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 1981ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 200b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 210b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" 220b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" 230b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" 240b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 250b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 260b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 270b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 280b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" 290b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 300b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 310b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 320b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 330b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" 3481ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFListTable.h" 3581ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" 3681ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" 370b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFSection.h" 3881ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 390b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 400b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" 41349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 420b57cec5SDimitry Andric #include "llvm/Object/Decompressor.h" 430b57cec5SDimitry Andric #include "llvm/Object/MachO.h" 440b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 450b57cec5SDimitry Andric #include "llvm/Object/RelocationResolver.h" 460b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 470b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 480b57cec5SDimitry Andric #include "llvm/Support/Error.h" 490b57cec5SDimitry Andric #include "llvm/Support/Format.h" 500b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 5106c3fb27SDimitry Andric #include "llvm/Support/FormatVariadic.h" 520b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 530b57cec5SDimitry Andric #include "llvm/Support/Path.h" 540b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 550b57cec5SDimitry Andric #include <algorithm> 560b57cec5SDimitry Andric #include <cstdint> 570b57cec5SDimitry Andric #include <deque> 580b57cec5SDimitry Andric #include <map> 590b57cec5SDimitry Andric #include <string> 600b57cec5SDimitry Andric #include <utility> 610b57cec5SDimitry Andric #include <vector> 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric using namespace llvm; 640b57cec5SDimitry Andric using namespace dwarf; 650b57cec5SDimitry Andric using namespace object; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric #define DEBUG_TYPE "dwarf" 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric using DWARFLineTable = DWARFDebugLine::LineTable; 700b57cec5SDimitry Andric using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; 710b57cec5SDimitry Andric using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; 720b57cec5SDimitry Andric 735f757f3fSDimitry Andric 745f757f3fSDimitry Andric void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index) { 755f757f3fSDimitry Andric using EntryType = DWARFUnitIndex::Entry::SectionContribution; 765f757f3fSDimitry Andric using EntryMap = DenseMap<uint32_t, EntryType>; 775f757f3fSDimitry Andric EntryMap Map; 785f757f3fSDimitry Andric const auto &DObj = C.getDWARFObj(); 795f757f3fSDimitry Andric if (DObj.getCUIndexSection().empty()) 805f757f3fSDimitry Andric return; 815f757f3fSDimitry Andric 825f757f3fSDimitry Andric uint64_t Offset = 0; 835f757f3fSDimitry Andric uint32_t TruncOffset = 0; 845f757f3fSDimitry Andric DObj.forEachInfoDWOSections([&](const DWARFSection &S) { 855f757f3fSDimitry Andric if (!(C.getParseCUTUIndexManually() || 865f757f3fSDimitry Andric S.Data.size() >= std::numeric_limits<uint32_t>::max())) 875f757f3fSDimitry Andric return; 885f757f3fSDimitry Andric 895f757f3fSDimitry Andric DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0); 905f757f3fSDimitry Andric while (Data.isValidOffset(Offset)) { 915f757f3fSDimitry Andric DWARFUnitHeader Header; 925f757f3fSDimitry Andric if (Error ExtractionErr = Header.extract( 935f757f3fSDimitry Andric C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) { 945f757f3fSDimitry Andric C.getWarningHandler()( 955f757f3fSDimitry Andric createError("Failed to parse CU header in DWP file: " + 965f757f3fSDimitry Andric toString(std::move(ExtractionErr)))); 975f757f3fSDimitry Andric Map.clear(); 985f757f3fSDimitry Andric break; 995f757f3fSDimitry Andric } 1005f757f3fSDimitry Andric 1015f757f3fSDimitry Andric auto Iter = Map.insert({TruncOffset, 1025f757f3fSDimitry Andric {Header.getOffset(), Header.getNextUnitOffset() - 1035f757f3fSDimitry Andric Header.getOffset()}}); 1045f757f3fSDimitry Andric if (!Iter.second) { 1055f757f3fSDimitry Andric logAllUnhandledErrors( 1065f757f3fSDimitry Andric createError("Collision occured between for truncated offset 0x" + 1075f757f3fSDimitry Andric Twine::utohexstr(TruncOffset)), 1085f757f3fSDimitry Andric errs()); 1095f757f3fSDimitry Andric Map.clear(); 1105f757f3fSDimitry Andric return; 1115f757f3fSDimitry Andric } 1125f757f3fSDimitry Andric 1135f757f3fSDimitry Andric Offset = Header.getNextUnitOffset(); 1145f757f3fSDimitry Andric TruncOffset = Offset; 1155f757f3fSDimitry Andric } 1165f757f3fSDimitry Andric }); 1175f757f3fSDimitry Andric 1185f757f3fSDimitry Andric if (Map.empty()) 1195f757f3fSDimitry Andric return; 1205f757f3fSDimitry Andric 1215f757f3fSDimitry Andric for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) { 1225f757f3fSDimitry Andric if (!E.isValid()) 1235f757f3fSDimitry Andric continue; 1245f757f3fSDimitry Andric DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution(); 1255f757f3fSDimitry Andric auto Iter = Map.find(CUOff.getOffset()); 1265f757f3fSDimitry Andric if (Iter == Map.end()) { 1275f757f3fSDimitry Andric logAllUnhandledErrors(createError("Could not find CU offset 0x" + 1285f757f3fSDimitry Andric Twine::utohexstr(CUOff.getOffset()) + 1295f757f3fSDimitry Andric " in the Map"), 1305f757f3fSDimitry Andric errs()); 1315f757f3fSDimitry Andric break; 1325f757f3fSDimitry Andric } 1335f757f3fSDimitry Andric CUOff.setOffset(Iter->second.getOffset()); 1345f757f3fSDimitry Andric if (CUOff.getOffset() != Iter->second.getOffset()) 1355f757f3fSDimitry Andric logAllUnhandledErrors(createError("Length of CU in CU index doesn't " 1365f757f3fSDimitry Andric "match calculated length at offset 0x" + 1375f757f3fSDimitry Andric Twine::utohexstr(CUOff.getOffset())), 1385f757f3fSDimitry Andric errs()); 1395f757f3fSDimitry Andric } 1405f757f3fSDimitry Andric } 1415f757f3fSDimitry Andric 1425f757f3fSDimitry Andric void fixupIndexV5(DWARFContext &C, DWARFUnitIndex &Index) { 1435f757f3fSDimitry Andric DenseMap<uint64_t, uint64_t> Map; 1445f757f3fSDimitry Andric 1455f757f3fSDimitry Andric const auto &DObj = C.getDWARFObj(); 1465f757f3fSDimitry Andric DObj.forEachInfoDWOSections([&](const DWARFSection &S) { 1475f757f3fSDimitry Andric if (!(C.getParseCUTUIndexManually() || 1485f757f3fSDimitry Andric S.Data.size() >= std::numeric_limits<uint32_t>::max())) 1495f757f3fSDimitry Andric return; 1505f757f3fSDimitry Andric DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0); 1515f757f3fSDimitry Andric uint64_t Offset = 0; 1525f757f3fSDimitry Andric while (Data.isValidOffset(Offset)) { 1535f757f3fSDimitry Andric DWARFUnitHeader Header; 1545f757f3fSDimitry Andric if (Error ExtractionErr = Header.extract( 1555f757f3fSDimitry Andric C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) { 1565f757f3fSDimitry Andric C.getWarningHandler()( 1575f757f3fSDimitry Andric createError("Failed to parse CU header in DWP file: " + 1585f757f3fSDimitry Andric toString(std::move(ExtractionErr)))); 1595f757f3fSDimitry Andric break; 1605f757f3fSDimitry Andric } 1615f757f3fSDimitry Andric bool CU = Header.getUnitType() == DW_UT_split_compile; 1625f757f3fSDimitry Andric uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash(); 1635f757f3fSDimitry Andric Map[Sig] = Header.getOffset(); 1645f757f3fSDimitry Andric Offset = Header.getNextUnitOffset(); 1655f757f3fSDimitry Andric } 1665f757f3fSDimitry Andric }); 1675f757f3fSDimitry Andric if (Map.empty()) 1685f757f3fSDimitry Andric return; 1695f757f3fSDimitry Andric for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) { 1705f757f3fSDimitry Andric if (!E.isValid()) 1715f757f3fSDimitry Andric continue; 1725f757f3fSDimitry Andric DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution(); 1735f757f3fSDimitry Andric auto Iter = Map.find(E.getSignature()); 1745f757f3fSDimitry Andric if (Iter == Map.end()) { 1755f757f3fSDimitry Andric logAllUnhandledErrors( 1765f757f3fSDimitry Andric createError("Could not find unit with signature 0x" + 1775f757f3fSDimitry Andric Twine::utohexstr(E.getSignature()) + " in the Map"), 1785f757f3fSDimitry Andric errs()); 1795f757f3fSDimitry Andric break; 1805f757f3fSDimitry Andric } 1815f757f3fSDimitry Andric CUOff.setOffset(Iter->second); 1825f757f3fSDimitry Andric } 1835f757f3fSDimitry Andric } 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric void fixupIndex(DWARFContext &C, DWARFUnitIndex &Index) { 1865f757f3fSDimitry Andric if (Index.getVersion() < 5) 1875f757f3fSDimitry Andric fixupIndexV4(C, Index); 1885f757f3fSDimitry Andric else 1895f757f3fSDimitry Andric fixupIndexV5(C, Index); 1905f757f3fSDimitry Andric } 1915f757f3fSDimitry Andric 1925f757f3fSDimitry Andric template <typename T> 1935f757f3fSDimitry Andric static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj, 1945f757f3fSDimitry Andric const DWARFSection &Section, StringRef StringSection, 1955f757f3fSDimitry Andric bool IsLittleEndian) { 1965f757f3fSDimitry Andric if (Cache) 1975f757f3fSDimitry Andric return *Cache; 1985f757f3fSDimitry Andric DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0); 1995f757f3fSDimitry Andric DataExtractor StrData(StringSection, IsLittleEndian, 0); 2005f757f3fSDimitry Andric Cache = std::make_unique<T>(AccelSection, StrData); 2015f757f3fSDimitry Andric if (Error E = Cache->extract()) 2025f757f3fSDimitry Andric llvm::consumeError(std::move(E)); 2035f757f3fSDimitry Andric return *Cache; 2045f757f3fSDimitry Andric } 2055f757f3fSDimitry Andric 2065f757f3fSDimitry Andric 2075f757f3fSDimitry Andric std::unique_ptr<DWARFDebugMacro> 2085f757f3fSDimitry Andric DWARFContext::DWARFContextState::parseMacroOrMacinfo(MacroSecType SectionType) { 2095f757f3fSDimitry Andric auto Macro = std::make_unique<DWARFDebugMacro>(); 2105f757f3fSDimitry Andric auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) { 2115f757f3fSDimitry Andric if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection 2125f757f3fSDimitry Andric ? D.compile_units() 2135f757f3fSDimitry Andric : D.dwo_compile_units(), 2145f757f3fSDimitry Andric SectionType == MacroSection 2155f757f3fSDimitry Andric ? D.getStringExtractor() 2165f757f3fSDimitry Andric : D.getStringDWOExtractor(), 2175f757f3fSDimitry Andric Data) 2185f757f3fSDimitry Andric : Macro->parseMacinfo(Data)) { 2195f757f3fSDimitry Andric D.getRecoverableErrorHandler()(std::move(Err)); 2205f757f3fSDimitry Andric Macro = nullptr; 2215f757f3fSDimitry Andric } 2225f757f3fSDimitry Andric }; 2235f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 2245f757f3fSDimitry Andric switch (SectionType) { 2255f757f3fSDimitry Andric case MacinfoSection: { 2265f757f3fSDimitry Andric DWARFDataExtractor Data(DObj.getMacinfoSection(), D.isLittleEndian(), 0); 2275f757f3fSDimitry Andric ParseAndDump(Data, /*IsMacro=*/false); 2285f757f3fSDimitry Andric break; 2295f757f3fSDimitry Andric } 2305f757f3fSDimitry Andric case MacinfoDwoSection: { 2315f757f3fSDimitry Andric DWARFDataExtractor Data(DObj.getMacinfoDWOSection(), D.isLittleEndian(), 0); 2325f757f3fSDimitry Andric ParseAndDump(Data, /*IsMacro=*/false); 2335f757f3fSDimitry Andric break; 2345f757f3fSDimitry Andric } 2355f757f3fSDimitry Andric case MacroSection: { 2365f757f3fSDimitry Andric DWARFDataExtractor Data(DObj, DObj.getMacroSection(), D.isLittleEndian(), 2375f757f3fSDimitry Andric 0); 2385f757f3fSDimitry Andric ParseAndDump(Data, /*IsMacro=*/true); 2395f757f3fSDimitry Andric break; 2405f757f3fSDimitry Andric } 2415f757f3fSDimitry Andric case MacroDwoSection: { 2425f757f3fSDimitry Andric DWARFDataExtractor Data(DObj.getMacroDWOSection(), D.isLittleEndian(), 0); 2435f757f3fSDimitry Andric ParseAndDump(Data, /*IsMacro=*/true); 2445f757f3fSDimitry Andric break; 2455f757f3fSDimitry Andric } 2465f757f3fSDimitry Andric } 2475f757f3fSDimitry Andric return Macro; 2485f757f3fSDimitry Andric } 2495f757f3fSDimitry Andric 250*0fca6ea1SDimitry Andric namespace { 2515f757f3fSDimitry Andric class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState { 2525f757f3fSDimitry Andric 2535f757f3fSDimitry Andric DWARFUnitVector NormalUnits; 2545f757f3fSDimitry Andric std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits; 2555f757f3fSDimitry Andric std::unique_ptr<DWARFUnitIndex> CUIndex; 2565f757f3fSDimitry Andric std::unique_ptr<DWARFGdbIndex> GdbIndex; 2575f757f3fSDimitry Andric std::unique_ptr<DWARFUnitIndex> TUIndex; 2585f757f3fSDimitry Andric std::unique_ptr<DWARFDebugAbbrev> Abbrev; 2595f757f3fSDimitry Andric std::unique_ptr<DWARFDebugLoc> Loc; 2605f757f3fSDimitry Andric std::unique_ptr<DWARFDebugAranges> Aranges; 2615f757f3fSDimitry Andric std::unique_ptr<DWARFDebugLine> Line; 2625f757f3fSDimitry Andric std::unique_ptr<DWARFDebugFrame> DebugFrame; 2635f757f3fSDimitry Andric std::unique_ptr<DWARFDebugFrame> EHFrame; 2645f757f3fSDimitry Andric std::unique_ptr<DWARFDebugMacro> Macro; 2655f757f3fSDimitry Andric std::unique_ptr<DWARFDebugMacro> Macinfo; 2665f757f3fSDimitry Andric std::unique_ptr<DWARFDebugNames> Names; 2675f757f3fSDimitry Andric std::unique_ptr<AppleAcceleratorTable> AppleNames; 2685f757f3fSDimitry Andric std::unique_ptr<AppleAcceleratorTable> AppleTypes; 2695f757f3fSDimitry Andric std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; 2705f757f3fSDimitry Andric std::unique_ptr<AppleAcceleratorTable> AppleObjC; 2715f757f3fSDimitry Andric DWARFUnitVector DWOUnits; 2725f757f3fSDimitry Andric std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits; 2735f757f3fSDimitry Andric std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; 2745f757f3fSDimitry Andric std::unique_ptr<DWARFDebugMacro> MacinfoDWO; 2755f757f3fSDimitry Andric std::unique_ptr<DWARFDebugMacro> MacroDWO; 2765f757f3fSDimitry Andric struct DWOFile { 2775f757f3fSDimitry Andric object::OwningBinary<object::ObjectFile> File; 2785f757f3fSDimitry Andric std::unique_ptr<DWARFContext> Context; 2795f757f3fSDimitry Andric }; 2805f757f3fSDimitry Andric StringMap<std::weak_ptr<DWOFile>> DWOFiles; 2815f757f3fSDimitry Andric std::weak_ptr<DWOFile> DWP; 2825f757f3fSDimitry Andric bool CheckedForDWP = false; 2835f757f3fSDimitry Andric std::string DWPName; 2845f757f3fSDimitry Andric 2855f757f3fSDimitry Andric public: 2865f757f3fSDimitry Andric ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) : 2875f757f3fSDimitry Andric DWARFContext::DWARFContextState(DC), 2885f757f3fSDimitry Andric DWPName(std::move(DWP)) {} 2895f757f3fSDimitry Andric 2905f757f3fSDimitry Andric DWARFUnitVector &getNormalUnits() override { 2915f757f3fSDimitry Andric if (NormalUnits.empty()) { 2925f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 2935f757f3fSDimitry Andric DObj.forEachInfoSections([&](const DWARFSection &S) { 2945f757f3fSDimitry Andric NormalUnits.addUnitsForSection(D, S, DW_SECT_INFO); 2955f757f3fSDimitry Andric }); 2965f757f3fSDimitry Andric NormalUnits.finishedInfoUnits(); 2975f757f3fSDimitry Andric DObj.forEachTypesSections([&](const DWARFSection &S) { 2985f757f3fSDimitry Andric NormalUnits.addUnitsForSection(D, S, DW_SECT_EXT_TYPES); 2995f757f3fSDimitry Andric }); 3005f757f3fSDimitry Andric } 3015f757f3fSDimitry Andric return NormalUnits; 3025f757f3fSDimitry Andric } 3035f757f3fSDimitry Andric 3045f757f3fSDimitry Andric DWARFUnitVector &getDWOUnits(bool Lazy) override { 3055f757f3fSDimitry Andric if (DWOUnits.empty()) { 3065f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 3075f757f3fSDimitry Andric 3085f757f3fSDimitry Andric DObj.forEachInfoDWOSections([&](const DWARFSection &S) { 3095f757f3fSDimitry Andric DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_INFO, Lazy); 3105f757f3fSDimitry Andric }); 3115f757f3fSDimitry Andric DWOUnits.finishedInfoUnits(); 3125f757f3fSDimitry Andric DObj.forEachTypesDWOSections([&](const DWARFSection &S) { 3135f757f3fSDimitry Andric DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_EXT_TYPES, Lazy); 3145f757f3fSDimitry Andric }); 3155f757f3fSDimitry Andric } 3165f757f3fSDimitry Andric return DWOUnits; 3175f757f3fSDimitry Andric } 3185f757f3fSDimitry Andric 3195f757f3fSDimitry Andric const DWARFDebugAbbrev *getDebugAbbrevDWO() override { 3205f757f3fSDimitry Andric if (AbbrevDWO) 3215f757f3fSDimitry Andric return AbbrevDWO.get(); 3225f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 3235f757f3fSDimitry Andric DataExtractor abbrData(DObj.getAbbrevDWOSection(), D.isLittleEndian(), 0); 3245f757f3fSDimitry Andric AbbrevDWO = std::make_unique<DWARFDebugAbbrev>(abbrData); 3255f757f3fSDimitry Andric return AbbrevDWO.get(); 3265f757f3fSDimitry Andric } 3275f757f3fSDimitry Andric 3285f757f3fSDimitry Andric const DWARFUnitIndex &getCUIndex() override { 3295f757f3fSDimitry Andric if (CUIndex) 3305f757f3fSDimitry Andric return *CUIndex; 3315f757f3fSDimitry Andric 3325f757f3fSDimitry Andric DataExtractor Data(D.getDWARFObj().getCUIndexSection(), 3335f757f3fSDimitry Andric D.isLittleEndian(), 0); 3345f757f3fSDimitry Andric CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO); 3355f757f3fSDimitry Andric if (CUIndex->parse(Data)) 3365f757f3fSDimitry Andric fixupIndex(D, *CUIndex); 3375f757f3fSDimitry Andric return *CUIndex; 3385f757f3fSDimitry Andric } 3395f757f3fSDimitry Andric const DWARFUnitIndex &getTUIndex() override { 3405f757f3fSDimitry Andric if (TUIndex) 3415f757f3fSDimitry Andric return *TUIndex; 3425f757f3fSDimitry Andric 3435f757f3fSDimitry Andric DataExtractor Data(D.getDWARFObj().getTUIndexSection(), 3445f757f3fSDimitry Andric D.isLittleEndian(), 0); 3455f757f3fSDimitry Andric TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES); 3465f757f3fSDimitry Andric bool isParseSuccessful = TUIndex->parse(Data); 3475f757f3fSDimitry Andric // If we are parsing TU-index and for .debug_types section we don't need 3485f757f3fSDimitry Andric // to do anything. 3495f757f3fSDimitry Andric if (isParseSuccessful && TUIndex->getVersion() != 2) 3505f757f3fSDimitry Andric fixupIndex(D, *TUIndex); 3515f757f3fSDimitry Andric return *TUIndex; 3525f757f3fSDimitry Andric } 3535f757f3fSDimitry Andric 3545f757f3fSDimitry Andric DWARFGdbIndex &getGdbIndex() override { 3555f757f3fSDimitry Andric if (GdbIndex) 3565f757f3fSDimitry Andric return *GdbIndex; 3575f757f3fSDimitry Andric 3585f757f3fSDimitry Andric DataExtractor Data(D.getDWARFObj().getGdbIndexSection(), true /*LE*/, 0); 3595f757f3fSDimitry Andric GdbIndex = std::make_unique<DWARFGdbIndex>(); 3605f757f3fSDimitry Andric GdbIndex->parse(Data); 3615f757f3fSDimitry Andric return *GdbIndex; 3625f757f3fSDimitry Andric } 3635f757f3fSDimitry Andric 3645f757f3fSDimitry Andric const DWARFDebugAbbrev *getDebugAbbrev() override { 3655f757f3fSDimitry Andric if (Abbrev) 3665f757f3fSDimitry Andric return Abbrev.get(); 3675f757f3fSDimitry Andric 3685f757f3fSDimitry Andric DataExtractor Data(D.getDWARFObj().getAbbrevSection(), 3695f757f3fSDimitry Andric D.isLittleEndian(), 0); 3705f757f3fSDimitry Andric Abbrev = std::make_unique<DWARFDebugAbbrev>(Data); 3715f757f3fSDimitry Andric return Abbrev.get(); 3725f757f3fSDimitry Andric } 3735f757f3fSDimitry Andric 3745f757f3fSDimitry Andric const DWARFDebugLoc *getDebugLoc() override { 3755f757f3fSDimitry Andric if (Loc) 3765f757f3fSDimitry Andric return Loc.get(); 3775f757f3fSDimitry Andric 3785f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 3795f757f3fSDimitry Andric // Assume all units have the same address byte size. 3805f757f3fSDimitry Andric auto Data = 3815f757f3fSDimitry Andric D.getNumCompileUnits() 3825f757f3fSDimitry Andric ? DWARFDataExtractor(DObj, DObj.getLocSection(), D.isLittleEndian(), 3835f757f3fSDimitry Andric D.getUnitAtIndex(0)->getAddressByteSize()) 3845f757f3fSDimitry Andric : DWARFDataExtractor("", D.isLittleEndian(), 0); 3855f757f3fSDimitry Andric Loc = std::make_unique<DWARFDebugLoc>(std::move(Data)); 3865f757f3fSDimitry Andric return Loc.get(); 3875f757f3fSDimitry Andric } 3885f757f3fSDimitry Andric 3895f757f3fSDimitry Andric const DWARFDebugAranges *getDebugAranges() override { 3905f757f3fSDimitry Andric if (Aranges) 3915f757f3fSDimitry Andric return Aranges.get(); 3925f757f3fSDimitry Andric 3935f757f3fSDimitry Andric Aranges = std::make_unique<DWARFDebugAranges>(); 3945f757f3fSDimitry Andric Aranges->generate(&D); 3955f757f3fSDimitry Andric return Aranges.get(); 3965f757f3fSDimitry Andric } 3975f757f3fSDimitry Andric 3985f757f3fSDimitry Andric Expected<const DWARFDebugLine::LineTable *> 3995f757f3fSDimitry Andric getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override { 4005f757f3fSDimitry Andric if (!Line) 4015f757f3fSDimitry Andric Line = std::make_unique<DWARFDebugLine>(); 4025f757f3fSDimitry Andric 4035f757f3fSDimitry Andric auto UnitDIE = U->getUnitDIE(); 4045f757f3fSDimitry Andric if (!UnitDIE) 4055f757f3fSDimitry Andric return nullptr; 4065f757f3fSDimitry Andric 4075f757f3fSDimitry Andric auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list)); 4085f757f3fSDimitry Andric if (!Offset) 4095f757f3fSDimitry Andric return nullptr; // No line table for this compile unit. 4105f757f3fSDimitry Andric 4115f757f3fSDimitry Andric uint64_t stmtOffset = *Offset + U->getLineTableOffset(); 4125f757f3fSDimitry Andric // See if the line table is cached. 4135f757f3fSDimitry Andric if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) 4145f757f3fSDimitry Andric return lt; 4155f757f3fSDimitry Andric 4165f757f3fSDimitry Andric // Make sure the offset is good before we try to parse. 4175f757f3fSDimitry Andric if (stmtOffset >= U->getLineSection().Data.size()) 4185f757f3fSDimitry Andric return nullptr; 4195f757f3fSDimitry Andric 4205f757f3fSDimitry Andric // We have to parse it first. 4215f757f3fSDimitry Andric DWARFDataExtractor Data(U->getContext().getDWARFObj(), U->getLineSection(), 4225f757f3fSDimitry Andric U->isLittleEndian(), U->getAddressByteSize()); 4235f757f3fSDimitry Andric return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U, 4245f757f3fSDimitry Andric RecoverableErrorHandler); 4255f757f3fSDimitry Andric 4265f757f3fSDimitry Andric } 4275f757f3fSDimitry Andric 4285f757f3fSDimitry Andric void clearLineTableForUnit(DWARFUnit *U) override { 4295f757f3fSDimitry Andric if (!Line) 4305f757f3fSDimitry Andric return; 4315f757f3fSDimitry Andric 4325f757f3fSDimitry Andric auto UnitDIE = U->getUnitDIE(); 4335f757f3fSDimitry Andric if (!UnitDIE) 4345f757f3fSDimitry Andric return; 4355f757f3fSDimitry Andric 4365f757f3fSDimitry Andric auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list)); 4375f757f3fSDimitry Andric if (!Offset) 4385f757f3fSDimitry Andric return; 4395f757f3fSDimitry Andric 4405f757f3fSDimitry Andric uint64_t stmtOffset = *Offset + U->getLineTableOffset(); 4415f757f3fSDimitry Andric Line->clearLineTable(stmtOffset); 4425f757f3fSDimitry Andric } 4435f757f3fSDimitry Andric 4445f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getDebugFrame() override { 4455f757f3fSDimitry Andric if (DebugFrame) 4465f757f3fSDimitry Andric return DebugFrame.get(); 4475f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 4485f757f3fSDimitry Andric const DWARFSection &DS = DObj.getFrameSection(); 4495f757f3fSDimitry Andric 4505f757f3fSDimitry Andric // There's a "bug" in the DWARFv3 standard with respect to the target address 4515f757f3fSDimitry Andric // size within debug frame sections. While DWARF is supposed to be independent 4525f757f3fSDimitry Andric // of its container, FDEs have fields with size being "target address size", 4535f757f3fSDimitry Andric // which isn't specified in DWARF in general. It's only specified for CUs, but 4545f757f3fSDimitry Andric // .eh_frame can appear without a .debug_info section. Follow the example of 4555f757f3fSDimitry Andric // other tools (libdwarf) and extract this from the container (ObjectFile 4565f757f3fSDimitry Andric // provides this information). This problem is fixed in DWARFv4 4575f757f3fSDimitry Andric // See this dwarf-discuss discussion for more details: 4585f757f3fSDimitry Andric // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html 4595f757f3fSDimitry Andric DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(), 4605f757f3fSDimitry Andric DObj.getAddressSize()); 4615f757f3fSDimitry Andric auto DF = 4625f757f3fSDimitry Andric std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false, 4635f757f3fSDimitry Andric DS.Address); 4645f757f3fSDimitry Andric if (Error E = DF->parse(Data)) 4655f757f3fSDimitry Andric return std::move(E); 4665f757f3fSDimitry Andric 4675f757f3fSDimitry Andric DebugFrame.swap(DF); 4685f757f3fSDimitry Andric return DebugFrame.get(); 4695f757f3fSDimitry Andric } 4705f757f3fSDimitry Andric 4715f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getEHFrame() override { 4725f757f3fSDimitry Andric if (EHFrame) 4735f757f3fSDimitry Andric return EHFrame.get(); 4745f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 4755f757f3fSDimitry Andric 4765f757f3fSDimitry Andric const DWARFSection &DS = DObj.getEHFrameSection(); 4775f757f3fSDimitry Andric DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(), 4785f757f3fSDimitry Andric DObj.getAddressSize()); 4795f757f3fSDimitry Andric auto DF = 4805f757f3fSDimitry Andric std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true, 4815f757f3fSDimitry Andric DS.Address); 4825f757f3fSDimitry Andric if (Error E = DF->parse(Data)) 4835f757f3fSDimitry Andric return std::move(E); 4845f757f3fSDimitry Andric EHFrame.swap(DF); 4855f757f3fSDimitry Andric return EHFrame.get(); 4865f757f3fSDimitry Andric } 4875f757f3fSDimitry Andric 4885f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfo() override { 4895f757f3fSDimitry Andric if (!Macinfo) 4905f757f3fSDimitry Andric Macinfo = parseMacroOrMacinfo(MacinfoSection); 4915f757f3fSDimitry Andric return Macinfo.get(); 4925f757f3fSDimitry Andric } 4935f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfoDWO() override { 4945f757f3fSDimitry Andric if (!MacinfoDWO) 4955f757f3fSDimitry Andric MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection); 4965f757f3fSDimitry Andric return MacinfoDWO.get(); 4975f757f3fSDimitry Andric } 4985f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacro() override { 4995f757f3fSDimitry Andric if (!Macro) 5005f757f3fSDimitry Andric Macro = parseMacroOrMacinfo(MacroSection); 5015f757f3fSDimitry Andric return Macro.get(); 5025f757f3fSDimitry Andric } 5035f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacroDWO() override { 5045f757f3fSDimitry Andric if (!MacroDWO) 5055f757f3fSDimitry Andric MacroDWO = parseMacroOrMacinfo(MacroDwoSection); 5065f757f3fSDimitry Andric return MacroDWO.get(); 5075f757f3fSDimitry Andric } 5085f757f3fSDimitry Andric const DWARFDebugNames &getDebugNames() override { 5095f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5105f757f3fSDimitry Andric return getAccelTable(Names, DObj, DObj.getNamesSection(), 5115f757f3fSDimitry Andric DObj.getStrSection(), D.isLittleEndian()); 5125f757f3fSDimitry Andric } 5135f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNames() override { 5145f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5155f757f3fSDimitry Andric return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(), 5165f757f3fSDimitry Andric DObj.getStrSection(), D.isLittleEndian()); 5175f757f3fSDimitry Andric 5185f757f3fSDimitry Andric } 5195f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleTypes() override { 5205f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5215f757f3fSDimitry Andric return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(), 5225f757f3fSDimitry Andric DObj.getStrSection(), D.isLittleEndian()); 5235f757f3fSDimitry Andric 5245f757f3fSDimitry Andric } 5255f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNamespaces() override { 5265f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5275f757f3fSDimitry Andric return getAccelTable(AppleNamespaces, DObj, 5285f757f3fSDimitry Andric DObj.getAppleNamespacesSection(), 5295f757f3fSDimitry Andric DObj.getStrSection(), D.isLittleEndian()); 5305f757f3fSDimitry Andric 5315f757f3fSDimitry Andric } 5325f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleObjC() override { 5335f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5345f757f3fSDimitry Andric return getAccelTable(AppleObjC, DObj, DObj.getAppleObjCSection(), 5355f757f3fSDimitry Andric DObj.getStrSection(), D.isLittleEndian()); 5365f757f3fSDimitry Andric } 5375f757f3fSDimitry Andric 5385f757f3fSDimitry Andric std::shared_ptr<DWARFContext> 5395f757f3fSDimitry Andric getDWOContext(StringRef AbsolutePath) override { 5405f757f3fSDimitry Andric if (auto S = DWP.lock()) { 5415f757f3fSDimitry Andric DWARFContext *Ctxt = S->Context.get(); 5425f757f3fSDimitry Andric return std::shared_ptr<DWARFContext>(std::move(S), Ctxt); 5435f757f3fSDimitry Andric } 5445f757f3fSDimitry Andric 5455f757f3fSDimitry Andric std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath]; 5465f757f3fSDimitry Andric 5475f757f3fSDimitry Andric if (auto S = Entry->lock()) { 5485f757f3fSDimitry Andric DWARFContext *Ctxt = S->Context.get(); 5495f757f3fSDimitry Andric return std::shared_ptr<DWARFContext>(std::move(S), Ctxt); 5505f757f3fSDimitry Andric } 5515f757f3fSDimitry Andric 5525f757f3fSDimitry Andric const DWARFObject &DObj = D.getDWARFObj(); 5535f757f3fSDimitry Andric 5545f757f3fSDimitry Andric Expected<OwningBinary<ObjectFile>> Obj = [&] { 5555f757f3fSDimitry Andric if (!CheckedForDWP) { 5565f757f3fSDimitry Andric SmallString<128> DWPName; 5575f757f3fSDimitry Andric auto Obj = object::ObjectFile::createObjectFile( 5585f757f3fSDimitry Andric this->DWPName.empty() 5595f757f3fSDimitry Andric ? (DObj.getFileName() + ".dwp").toStringRef(DWPName) 5605f757f3fSDimitry Andric : StringRef(this->DWPName)); 5615f757f3fSDimitry Andric if (Obj) { 5625f757f3fSDimitry Andric Entry = &DWP; 5635f757f3fSDimitry Andric return Obj; 5645f757f3fSDimitry Andric } else { 5655f757f3fSDimitry Andric CheckedForDWP = true; 5665f757f3fSDimitry Andric // TODO: Should this error be handled (maybe in a high verbosity mode) 5675f757f3fSDimitry Andric // before falling back to .dwo files? 5685f757f3fSDimitry Andric consumeError(Obj.takeError()); 5695f757f3fSDimitry Andric } 5705f757f3fSDimitry Andric } 5715f757f3fSDimitry Andric 5725f757f3fSDimitry Andric return object::ObjectFile::createObjectFile(AbsolutePath); 5735f757f3fSDimitry Andric }(); 5745f757f3fSDimitry Andric 5755f757f3fSDimitry Andric if (!Obj) { 5765f757f3fSDimitry Andric // TODO: Actually report errors helpfully. 5775f757f3fSDimitry Andric consumeError(Obj.takeError()); 5785f757f3fSDimitry Andric return nullptr; 5795f757f3fSDimitry Andric } 5805f757f3fSDimitry Andric 5815f757f3fSDimitry Andric auto S = std::make_shared<DWOFile>(); 5825f757f3fSDimitry Andric S->File = std::move(Obj.get()); 5835f757f3fSDimitry Andric // Allow multi-threaded access if there is a .dwp file as the CU index and 5845f757f3fSDimitry Andric // TU index might be accessed from multiple threads. 5855f757f3fSDimitry Andric bool ThreadSafe = isThreadSafe(); 5865f757f3fSDimitry Andric S->Context = DWARFContext::create( 5875f757f3fSDimitry Andric *S->File.getBinary(), DWARFContext::ProcessDebugRelocations::Ignore, 5885f757f3fSDimitry Andric nullptr, "", WithColor::defaultErrorHandler, 5895f757f3fSDimitry Andric WithColor::defaultWarningHandler, ThreadSafe); 5905f757f3fSDimitry Andric *Entry = S; 5915f757f3fSDimitry Andric auto *Ctxt = S->Context.get(); 5925f757f3fSDimitry Andric return std::shared_ptr<DWARFContext>(std::move(S), Ctxt); 5935f757f3fSDimitry Andric } 5945f757f3fSDimitry Andric 5955f757f3fSDimitry Andric bool isThreadSafe() const override { return false; } 5965f757f3fSDimitry Andric 5975f757f3fSDimitry Andric const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() { 5985f757f3fSDimitry Andric if (!NormalTypeUnits) { 5995f757f3fSDimitry Andric NormalTypeUnits.emplace(); 6005f757f3fSDimitry Andric for (const auto &U :D.normal_units()) { 6015f757f3fSDimitry Andric if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get())) 6025f757f3fSDimitry Andric (*NormalTypeUnits)[TU->getTypeHash()] = TU; 6035f757f3fSDimitry Andric } 6045f757f3fSDimitry Andric } 6055f757f3fSDimitry Andric return *NormalTypeUnits; 6065f757f3fSDimitry Andric } 6075f757f3fSDimitry Andric 6085f757f3fSDimitry Andric const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() { 6095f757f3fSDimitry Andric if (!DWOTypeUnits) { 6105f757f3fSDimitry Andric DWOTypeUnits.emplace(); 6115f757f3fSDimitry Andric for (const auto &U :D.dwo_units()) { 6125f757f3fSDimitry Andric if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get())) 6135f757f3fSDimitry Andric (*DWOTypeUnits)[TU->getTypeHash()] = TU; 6145f757f3fSDimitry Andric } 6155f757f3fSDimitry Andric } 6165f757f3fSDimitry Andric return *DWOTypeUnits; 6175f757f3fSDimitry Andric } 6185f757f3fSDimitry Andric 6195f757f3fSDimitry Andric const DenseMap<uint64_t, DWARFTypeUnit *> & 6205f757f3fSDimitry Andric getTypeUnitMap(bool IsDWO) override { 6215f757f3fSDimitry Andric if (IsDWO) 6225f757f3fSDimitry Andric return getDWOTypeUnitMap(); 6235f757f3fSDimitry Andric else 6245f757f3fSDimitry Andric return getNormalTypeUnitMap(); 6255f757f3fSDimitry Andric } 6265f757f3fSDimitry Andric 6275f757f3fSDimitry Andric 6285f757f3fSDimitry Andric }; 6295f757f3fSDimitry Andric 6305f757f3fSDimitry Andric class ThreadSafeState : public ThreadUnsafeDWARFContextState { 6315f757f3fSDimitry Andric std::recursive_mutex Mutex; 6325f757f3fSDimitry Andric 6335f757f3fSDimitry Andric public: 6345f757f3fSDimitry Andric ThreadSafeState(DWARFContext &DC, std::string &DWP) : 6355f757f3fSDimitry Andric ThreadUnsafeDWARFContextState(DC, DWP) {} 6365f757f3fSDimitry Andric 6375f757f3fSDimitry Andric DWARFUnitVector &getNormalUnits() override { 6385f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6395f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getNormalUnits(); 6405f757f3fSDimitry Andric } 6415f757f3fSDimitry Andric DWARFUnitVector &getDWOUnits(bool Lazy) override { 6425f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6435f757f3fSDimitry Andric // We need to not do lazy parsing when we need thread safety as 6445f757f3fSDimitry Andric // DWARFUnitVector, in lazy mode, will slowly add things to itself and 6455f757f3fSDimitry Andric // will cause problems in a multi-threaded environment. 6465f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDWOUnits(false); 6475f757f3fSDimitry Andric } 6485f757f3fSDimitry Andric const DWARFUnitIndex &getCUIndex() override { 6495f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6505f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getCUIndex(); 6515f757f3fSDimitry Andric } 6525f757f3fSDimitry Andric const DWARFDebugAbbrev *getDebugAbbrevDWO() override { 6535f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6545f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugAbbrevDWO(); 6555f757f3fSDimitry Andric } 6565f757f3fSDimitry Andric 6575f757f3fSDimitry Andric const DWARFUnitIndex &getTUIndex() override { 6585f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6595f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getTUIndex(); 6605f757f3fSDimitry Andric } 6615f757f3fSDimitry Andric DWARFGdbIndex &getGdbIndex() override { 6625f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6635f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getGdbIndex(); 6645f757f3fSDimitry Andric } 6655f757f3fSDimitry Andric const DWARFDebugAbbrev *getDebugAbbrev() override { 6665f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6675f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugAbbrev(); 6685f757f3fSDimitry Andric } 6695f757f3fSDimitry Andric const DWARFDebugLoc *getDebugLoc() override { 6705f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6715f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugLoc(); 6725f757f3fSDimitry Andric } 6735f757f3fSDimitry Andric const DWARFDebugAranges *getDebugAranges() override { 6745f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6755f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugAranges(); 6765f757f3fSDimitry Andric } 6775f757f3fSDimitry Andric Expected<const DWARFDebugLine::LineTable *> 6785f757f3fSDimitry Andric getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override { 6795f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6805f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler); 6815f757f3fSDimitry Andric } 6825f757f3fSDimitry Andric void clearLineTableForUnit(DWARFUnit *U) override { 6835f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6845f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::clearLineTableForUnit(U); 6855f757f3fSDimitry Andric } 6865f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getDebugFrame() override { 6875f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6885f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugFrame(); 6895f757f3fSDimitry Andric } 6905f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getEHFrame() override { 6915f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6925f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getEHFrame(); 6935f757f3fSDimitry Andric } 6945f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfo() override { 6955f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 6965f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacinfo(); 6975f757f3fSDimitry Andric } 6985f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfoDWO() override { 6995f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7005f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO(); 7015f757f3fSDimitry Andric } 7025f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacro() override { 7035f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7045f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacro(); 7055f757f3fSDimitry Andric } 7065f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacroDWO() override { 7075f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7085f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacroDWO(); 7095f757f3fSDimitry Andric } 7105f757f3fSDimitry Andric const DWARFDebugNames &getDebugNames() override { 7115f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7125f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugNames(); 7135f757f3fSDimitry Andric } 7145f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNames() override { 7155f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7165f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleNames(); 7175f757f3fSDimitry Andric } 7185f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleTypes() override { 7195f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7205f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleTypes(); 7215f757f3fSDimitry Andric } 7225f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNamespaces() override { 7235f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7245f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleNamespaces(); 7255f757f3fSDimitry Andric } 7265f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleObjC() override { 7275f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7285f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleObjC(); 7295f757f3fSDimitry Andric } 7305f757f3fSDimitry Andric std::shared_ptr<DWARFContext> 7315f757f3fSDimitry Andric getDWOContext(StringRef AbsolutePath) override { 7325f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7335f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath); 7345f757f3fSDimitry Andric } 7355f757f3fSDimitry Andric 7365f757f3fSDimitry Andric bool isThreadSafe() const override { return true; } 7375f757f3fSDimitry Andric 7385f757f3fSDimitry Andric const DenseMap<uint64_t, DWARFTypeUnit *> & 7395f757f3fSDimitry Andric getTypeUnitMap(bool IsDWO) override { 7405f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex); 7415f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO); 7425f757f3fSDimitry Andric } 7435f757f3fSDimitry Andric }; 744*0fca6ea1SDimitry Andric } // namespace 7455f757f3fSDimitry Andric 7460b57cec5SDimitry Andric DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj, 7475ffd83dbSDimitry Andric std::string DWPName, 7485ffd83dbSDimitry Andric std::function<void(Error)> RecoverableErrorHandler, 7495f757f3fSDimitry Andric std::function<void(Error)> WarningHandler, 7505f757f3fSDimitry Andric bool ThreadSafe) 7515f757f3fSDimitry Andric : DIContext(CK_DWARF), 7525ffd83dbSDimitry Andric RecoverableErrorHandler(RecoverableErrorHandler), 7535f757f3fSDimitry Andric WarningHandler(WarningHandler), DObj(std::move(DObj)) { 7545f757f3fSDimitry Andric if (ThreadSafe) 7555f757f3fSDimitry Andric State = std::make_unique<ThreadSafeState>(*this, DWPName); 7565f757f3fSDimitry Andric else 7575f757f3fSDimitry Andric State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName); 7585f757f3fSDimitry Andric } 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric DWARFContext::~DWARFContext() = default; 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric /// Dump the UUID load command. 7630b57cec5SDimitry Andric static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) { 7640b57cec5SDimitry Andric auto *MachO = dyn_cast<MachOObjectFile>(&Obj); 7650b57cec5SDimitry Andric if (!MachO) 7660b57cec5SDimitry Andric return; 7670b57cec5SDimitry Andric for (auto LC : MachO->load_commands()) { 7680b57cec5SDimitry Andric raw_ostream::uuid_t UUID; 7690b57cec5SDimitry Andric if (LC.C.cmd == MachO::LC_UUID) { 7700b57cec5SDimitry Andric if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) { 7710b57cec5SDimitry Andric OS << "error: UUID load command is too short.\n"; 7720b57cec5SDimitry Andric return; 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric OS << "UUID: "; 7750b57cec5SDimitry Andric memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID)); 7760b57cec5SDimitry Andric OS.write_uuid(UUID); 7770b57cec5SDimitry Andric Triple T = MachO->getArchTriple(); 7780b57cec5SDimitry Andric OS << " (" << T.getArchName() << ')'; 7790b57cec5SDimitry Andric OS << ' ' << MachO->getFileName() << '\n'; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric using ContributionCollection = 785bdd1243dSDimitry Andric std::vector<std::optional<StrOffsetsContributionDescriptor>>; 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric // Collect all the contributions to the string offsets table from all units, 7880b57cec5SDimitry Andric // sort them by their starting offsets and remove duplicates. 7890b57cec5SDimitry Andric static ContributionCollection 7900b57cec5SDimitry Andric collectContributionData(DWARFContext::unit_iterator_range Units) { 7910b57cec5SDimitry Andric ContributionCollection Contributions; 7920b57cec5SDimitry Andric for (const auto &U : Units) 7930b57cec5SDimitry Andric if (const auto &C = U->getStringOffsetsTableContribution()) 7940b57cec5SDimitry Andric Contributions.push_back(C); 7950b57cec5SDimitry Andric // Sort the contributions so that any invalid ones are placed at 7960b57cec5SDimitry Andric // the start of the contributions vector. This way they are reported 7970b57cec5SDimitry Andric // first. 7980b57cec5SDimitry Andric llvm::sort(Contributions, 799bdd1243dSDimitry Andric [](const std::optional<StrOffsetsContributionDescriptor> &L, 800bdd1243dSDimitry Andric const std::optional<StrOffsetsContributionDescriptor> &R) { 8010b57cec5SDimitry Andric if (L && R) 8020b57cec5SDimitry Andric return L->Base < R->Base; 80381ad6265SDimitry Andric return R.has_value(); 8040b57cec5SDimitry Andric }); 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric // Uniquify contributions, as it is possible that units (specifically 8070b57cec5SDimitry Andric // type units in dwo or dwp files) share contributions. We don't want 8080b57cec5SDimitry Andric // to report them more than once. 8090b57cec5SDimitry Andric Contributions.erase( 810*0fca6ea1SDimitry Andric llvm::unique( 811*0fca6ea1SDimitry Andric Contributions, 812bdd1243dSDimitry Andric [](const std::optional<StrOffsetsContributionDescriptor> &L, 813bdd1243dSDimitry Andric const std::optional<StrOffsetsContributionDescriptor> &R) { 8140b57cec5SDimitry Andric if (L && R) 8150b57cec5SDimitry Andric return L->Base == R->Base && L->Size == R->Size; 8160b57cec5SDimitry Andric return false; 8170b57cec5SDimitry Andric }), 8180b57cec5SDimitry Andric Contributions.end()); 8190b57cec5SDimitry Andric return Contributions; 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric 8225ffd83dbSDimitry Andric // Dump a DWARF string offsets section. This may be a DWARF v5 formatted 8235ffd83dbSDimitry Andric // string offsets section, where each compile or type unit contributes a 8245ffd83dbSDimitry Andric // number of entries (string offsets), with each contribution preceded by 8255ffd83dbSDimitry Andric // a header containing size and version number. Alternatively, it may be a 8265ffd83dbSDimitry Andric // monolithic series of string offsets, as generated by the pre-DWARF v5 8275ffd83dbSDimitry Andric // implementation of split DWARF; however, in that case we still need to 8285ffd83dbSDimitry Andric // collect contributions of units because the size of the offsets (4 or 8 8295ffd83dbSDimitry Andric // bytes) depends on the format of the referencing unit (DWARF32 or DWARF64). 8305ffd83dbSDimitry Andric static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts, 8315ffd83dbSDimitry Andric StringRef SectionName, 8325ffd83dbSDimitry Andric const DWARFObject &Obj, 8335ffd83dbSDimitry Andric const DWARFSection &StringOffsetsSection, 8345ffd83dbSDimitry Andric StringRef StringSection, 8355ffd83dbSDimitry Andric DWARFContext::unit_iterator_range Units, 8365ffd83dbSDimitry Andric bool LittleEndian) { 8370b57cec5SDimitry Andric auto Contributions = collectContributionData(Units); 8380b57cec5SDimitry Andric DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); 8390b57cec5SDimitry Andric DataExtractor StrData(StringSection, LittleEndian, 0); 8400b57cec5SDimitry Andric uint64_t SectionSize = StringOffsetsSection.Data.size(); 8418bcb0991SDimitry Andric uint64_t Offset = 0; 8420b57cec5SDimitry Andric for (auto &Contribution : Contributions) { 8430b57cec5SDimitry Andric // Report an ill-formed contribution. 8440b57cec5SDimitry Andric if (!Contribution) { 8450b57cec5SDimitry Andric OS << "error: invalid contribution to string offsets table in section ." 8460b57cec5SDimitry Andric << SectionName << ".\n"; 8470b57cec5SDimitry Andric return; 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric dwarf::DwarfFormat Format = Contribution->getFormat(); 8515ffd83dbSDimitry Andric int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format); 8520b57cec5SDimitry Andric uint16_t Version = Contribution->getVersion(); 8530b57cec5SDimitry Andric uint64_t ContributionHeader = Contribution->Base; 8540b57cec5SDimitry Andric // In DWARF v5 there is a contribution header that immediately precedes 8550b57cec5SDimitry Andric // the string offsets base (the location we have previously retrieved from 8560b57cec5SDimitry Andric // the CU DIE's DW_AT_str_offsets attribute). The header is located either 8570b57cec5SDimitry Andric // 8 or 16 bytes before the base, depending on the contribution's format. 8580b57cec5SDimitry Andric if (Version >= 5) 8590b57cec5SDimitry Andric ContributionHeader -= Format == DWARF32 ? 8 : 16; 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric // Detect overlapping contributions. 8620b57cec5SDimitry Andric if (Offset > ContributionHeader) { 8635ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(createStringError( 8645ffd83dbSDimitry Andric errc::invalid_argument, 8655ffd83dbSDimitry Andric "overlapping contributions to string offsets table in section .%s.", 8665ffd83dbSDimitry Andric SectionName.data())); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric // Report a gap in the table. 8690b57cec5SDimitry Andric if (Offset < ContributionHeader) { 8708bcb0991SDimitry Andric OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset); 8710b57cec5SDimitry Andric OS << (ContributionHeader - Offset) << "\n"; 8720b57cec5SDimitry Andric } 8738bcb0991SDimitry Andric OS << format("0x%8.8" PRIx64 ": ", ContributionHeader); 8740b57cec5SDimitry Andric // In DWARF v5 the contribution size in the descriptor does not equal 8750b57cec5SDimitry Andric // the originally encoded length (it does not contain the length of the 8760b57cec5SDimitry Andric // version field and the padding, a total of 4 bytes). Add them back in 8770b57cec5SDimitry Andric // for reporting. 8780b57cec5SDimitry Andric OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4)) 8795ffd83dbSDimitry Andric << ", Format = " << dwarf::FormatString(Format) 8800b57cec5SDimitry Andric << ", Version = " << Version << "\n"; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric Offset = Contribution->Base; 8830b57cec5SDimitry Andric unsigned EntrySize = Contribution->getDwarfOffsetByteSize(); 8840b57cec5SDimitry Andric while (Offset - Contribution->Base < Contribution->Size) { 8858bcb0991SDimitry Andric OS << format("0x%8.8" PRIx64 ": ", Offset); 8860b57cec5SDimitry Andric uint64_t StringOffset = 8870b57cec5SDimitry Andric StrOffsetExt.getRelocatedValue(EntrySize, &Offset); 8885ffd83dbSDimitry Andric OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset); 8898bcb0991SDimitry Andric const char *S = StrData.getCStr(&StringOffset); 8900b57cec5SDimitry Andric if (S) 8910b57cec5SDimitry Andric OS << format("\"%s\"", S); 8920b57cec5SDimitry Andric OS << "\n"; 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric } 8950b57cec5SDimitry Andric // Report a gap at the end of the table. 8960b57cec5SDimitry Andric if (Offset < SectionSize) { 8978bcb0991SDimitry Andric OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset); 8980b57cec5SDimitry Andric OS << (SectionSize - Offset) << "\n"; 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric } 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric // Dump the .debug_addr section. 9030b57cec5SDimitry Andric static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, 9040b57cec5SDimitry Andric DIDumpOptions DumpOpts, uint16_t Version, 9050b57cec5SDimitry Andric uint8_t AddrSize) { 9068bcb0991SDimitry Andric uint64_t Offset = 0; 9070b57cec5SDimitry Andric while (AddrData.isValidOffset(Offset)) { 9080b57cec5SDimitry Andric DWARFDebugAddrTable AddrTable; 9098bcb0991SDimitry Andric uint64_t TableOffset = Offset; 9100b57cec5SDimitry Andric if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize, 9115ffd83dbSDimitry Andric DumpOpts.WarningHandler)) { 9125ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(std::move(Err)); 9130b57cec5SDimitry Andric // Keep going after an error, if we can, assuming that the length field 9140b57cec5SDimitry Andric // could be read. If it couldn't, stop reading the section. 9155ffd83dbSDimitry Andric if (auto TableLength = AddrTable.getFullLength()) { 9165ffd83dbSDimitry Andric Offset = TableOffset + *TableLength; 9175ffd83dbSDimitry Andric continue; 9180b57cec5SDimitry Andric } 9195ffd83dbSDimitry Andric break; 9205ffd83dbSDimitry Andric } 9215ffd83dbSDimitry Andric AddrTable.dump(OS, DumpOpts); 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). 9260b57cec5SDimitry Andric static void dumpRnglistsSection( 9270b57cec5SDimitry Andric raw_ostream &OS, DWARFDataExtractor &rnglistData, 928bdd1243dSDimitry Andric llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)> 9290b57cec5SDimitry Andric LookupPooledAddress, 9300b57cec5SDimitry Andric DIDumpOptions DumpOpts) { 9318bcb0991SDimitry Andric uint64_t Offset = 0; 9320b57cec5SDimitry Andric while (rnglistData.isValidOffset(Offset)) { 9330b57cec5SDimitry Andric llvm::DWARFDebugRnglistTable Rnglists; 9348bcb0991SDimitry Andric uint64_t TableOffset = Offset; 9350b57cec5SDimitry Andric if (Error Err = Rnglists.extract(rnglistData, &Offset)) { 9365ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(std::move(Err)); 9370b57cec5SDimitry Andric uint64_t Length = Rnglists.length(); 9380b57cec5SDimitry Andric // Keep going after an error, if we can, assuming that the length field 9390b57cec5SDimitry Andric // could be read. If it couldn't, stop reading the section. 9400b57cec5SDimitry Andric if (Length == 0) 9410b57cec5SDimitry Andric break; 9420b57cec5SDimitry Andric Offset = TableOffset + Length; 9430b57cec5SDimitry Andric } else { 944e8d8bef9SDimitry Andric Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts); 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9495ffd83dbSDimitry Andric 9500b57cec5SDimitry Andric static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, 951bdd1243dSDimitry Andric DWARFDataExtractor Data, const DWARFObject &Obj, 952bdd1243dSDimitry Andric std::optional<uint64_t> DumpOffset) { 9538bcb0991SDimitry Andric uint64_t Offset = 0; 9540b57cec5SDimitry Andric 9558bcb0991SDimitry Andric while (Data.isValidOffset(Offset)) { 9560b57cec5SDimitry Andric DWARFListTableHeader Header(".debug_loclists", "locations"); 9570b57cec5SDimitry Andric if (Error E = Header.extract(Data, &Offset)) { 9585ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(std::move(E)); 9590b57cec5SDimitry Andric return; 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 962e8d8bef9SDimitry Andric Header.dump(Data, OS, DumpOpts); 9630b57cec5SDimitry Andric 9648bcb0991SDimitry Andric uint64_t EndOffset = Header.length() + Header.getHeaderOffset(); 965480093f4SDimitry Andric Data.setAddressSize(Header.getAddrSize()); 966480093f4SDimitry Andric DWARFDebugLoclists Loc(Data, Header.getVersion()); 967480093f4SDimitry Andric if (DumpOffset) { 968480093f4SDimitry Andric if (DumpOffset >= Offset && DumpOffset < EndOffset) { 969480093f4SDimitry Andric Offset = *DumpOffset; 970bdd1243dSDimitry Andric Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj, 971bdd1243dSDimitry Andric nullptr, DumpOpts, /*Indent=*/0); 972480093f4SDimitry Andric OS << "\n"; 973480093f4SDimitry Andric return; 974480093f4SDimitry Andric } 975480093f4SDimitry Andric } else { 976bdd1243dSDimitry Andric Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts); 977480093f4SDimitry Andric } 9788bcb0991SDimitry Andric Offset = EndOffset; 9798bcb0991SDimitry Andric } 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9825ffd83dbSDimitry Andric static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts, 9835ffd83dbSDimitry Andric DWARFDataExtractor Data, bool GnuStyle) { 9845ffd83dbSDimitry Andric DWARFDebugPubTable Table; 9855ffd83dbSDimitry Andric Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler); 9865ffd83dbSDimitry Andric Table.dump(OS); 9875ffd83dbSDimitry Andric } 9885ffd83dbSDimitry Andric 9890b57cec5SDimitry Andric void DWARFContext::dump( 9900b57cec5SDimitry Andric raw_ostream &OS, DIDumpOptions DumpOpts, 991bdd1243dSDimitry Andric std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) { 9920b57cec5SDimitry Andric uint64_t DumpType = DumpOpts.DumpType; 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric StringRef Extension = sys::path::extension(DObj->getFileName()); 9950b57cec5SDimitry Andric bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp"); 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric // Print UUID header. 9980b57cec5SDimitry Andric const auto *ObjFile = DObj->getFile(); 9990b57cec5SDimitry Andric if (DumpType & DIDT_UUID) 10000b57cec5SDimitry Andric dumpUUID(OS, *ObjFile); 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric // Print a header for each explicitly-requested section. 10030b57cec5SDimitry Andric // Otherwise just print one for non-empty sections. 10040b57cec5SDimitry Andric // Only print empty .dwo section headers when dumping a .dwo file. 10050b57cec5SDimitry Andric bool Explicit = DumpType != DIDT_All && !IsDWO; 10060b57cec5SDimitry Andric bool ExplicitDWO = Explicit && IsDWO; 10070b57cec5SDimitry Andric auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID, 1008bdd1243dSDimitry Andric StringRef Section) -> std::optional<uint64_t> * { 10090b57cec5SDimitry Andric unsigned Mask = 1U << ID; 10100b57cec5SDimitry Andric bool Should = (DumpType & Mask) && (Explicit || !Section.empty()); 10110b57cec5SDimitry Andric if (!Should) 10120b57cec5SDimitry Andric return nullptr; 10130b57cec5SDimitry Andric OS << "\n" << Name << " contents:\n"; 10140b57cec5SDimitry Andric return &DumpOffsets[ID]; 10150b57cec5SDimitry Andric }; 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric // Dump individual sections. 10180b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev, 10190b57cec5SDimitry Andric DObj->getAbbrevSection())) 10200b57cec5SDimitry Andric getDebugAbbrev()->dump(OS); 10210b57cec5SDimitry Andric if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev, 10220b57cec5SDimitry Andric DObj->getAbbrevDWOSection())) 10230b57cec5SDimitry Andric getDebugAbbrevDWO()->dump(OS); 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) { 10260b57cec5SDimitry Andric OS << '\n' << Name << " contents:\n"; 10270b57cec5SDimitry Andric if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) 10287a6dacacSDimitry Andric for (const auto &U : Units) { 102981ad6265SDimitry Andric U->getDIEForOffset(*DumpOffset) 10300b57cec5SDimitry Andric .dump(OS, 0, DumpOpts.noImplicitRecursion()); 10317a6dacacSDimitry Andric DWARFDie CUDie = U->getUnitDIE(false); 10327a6dacacSDimitry Andric DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false); 10337a6dacacSDimitry Andric if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) { 10347a6dacacSDimitry Andric CUNonSkeletonDie.getDwarfUnit() 10357a6dacacSDimitry Andric ->getDIEForOffset(*DumpOffset) 10367a6dacacSDimitry Andric .dump(OS, 0, DumpOpts.noImplicitRecursion()); 10377a6dacacSDimitry Andric } 10387a6dacacSDimitry Andric } 10390b57cec5SDimitry Andric else 10400b57cec5SDimitry Andric for (const auto &U : Units) 10410b57cec5SDimitry Andric U->dump(OS, DumpOpts); 10420b57cec5SDimitry Andric }; 10430b57cec5SDimitry Andric if ((DumpType & DIDT_DebugInfo)) { 10440b57cec5SDimitry Andric if (Explicit || getNumCompileUnits()) 10450b57cec5SDimitry Andric dumpDebugInfo(".debug_info", info_section_units()); 10460b57cec5SDimitry Andric if (ExplicitDWO || getNumDWOCompileUnits()) 10470b57cec5SDimitry Andric dumpDebugInfo(".debug_info.dwo", dwo_info_section_units()); 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) { 10510b57cec5SDimitry Andric OS << '\n' << Name << " contents:\n"; 10520b57cec5SDimitry Andric for (const auto &U : Units) 10530b57cec5SDimitry Andric if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes]) 10540b57cec5SDimitry Andric U->getDIEForOffset(*DumpOffset) 10550b57cec5SDimitry Andric .dump(OS, 0, DumpOpts.noImplicitRecursion()); 10560b57cec5SDimitry Andric else 10570b57cec5SDimitry Andric U->dump(OS, DumpOpts); 10580b57cec5SDimitry Andric }; 10590b57cec5SDimitry Andric if ((DumpType & DIDT_DebugTypes)) { 10600b57cec5SDimitry Andric if (Explicit || getNumTypeUnits()) 10610b57cec5SDimitry Andric dumpDebugType(".debug_types", types_section_units()); 10620b57cec5SDimitry Andric if (ExplicitDWO || getNumDWOTypeUnits()) 10630b57cec5SDimitry Andric dumpDebugType(".debug_types.dwo", dwo_types_section_units()); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 1066480093f4SDimitry Andric DIDumpOptions LLDumpOpts = DumpOpts; 1067480093f4SDimitry Andric if (LLDumpOpts.Verbose) 1068480093f4SDimitry Andric LLDumpOpts.DisplayRawContents = true; 1069480093f4SDimitry Andric 10700b57cec5SDimitry Andric if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, 10710b57cec5SDimitry Andric DObj->getLocSection().Data)) { 1072bdd1243dSDimitry Andric getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off); 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric if (const auto *Off = 10750b57cec5SDimitry Andric shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, 10760b57cec5SDimitry Andric DObj->getLoclistsSection().Data)) { 10770b57cec5SDimitry Andric DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), 10780b57cec5SDimitry Andric 0); 1079bdd1243dSDimitry Andric dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off); 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric if (const auto *Off = 1082480093f4SDimitry Andric shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, 1083480093f4SDimitry Andric DObj->getLoclistsDWOSection().Data)) { 1084480093f4SDimitry Andric DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), 1085480093f4SDimitry Andric isLittleEndian(), 0); 1086bdd1243dSDimitry Andric dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off); 1087480093f4SDimitry Andric } 1088480093f4SDimitry Andric 1089480093f4SDimitry Andric if (const auto *Off = 10900b57cec5SDimitry Andric shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, 10910b57cec5SDimitry Andric DObj->getLocDWOSection().Data)) { 1092480093f4SDimitry Andric DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(), 1093480093f4SDimitry Andric 4); 1094480093f4SDimitry Andric DWARFDebugLoclists Loc(Data, /*Version=*/4); 1095480093f4SDimitry Andric if (*Off) { 1096480093f4SDimitry Andric uint64_t Offset = **Off; 1097480093f4SDimitry Andric Loc.dumpLocationList(&Offset, OS, 1098bdd1243dSDimitry Andric /*BaseAddr=*/std::nullopt, *DObj, nullptr, 1099bdd1243dSDimitry Andric LLDumpOpts, 1100bdd1243dSDimitry Andric /*Indent=*/0); 1101480093f4SDimitry Andric OS << "\n"; 1102480093f4SDimitry Andric } else { 1103bdd1243dSDimitry Andric Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts); 1104480093f4SDimitry Andric } 11050b57cec5SDimitry Andric } 11060b57cec5SDimitry Andric 1107bdd1243dSDimitry Andric if (const std::optional<uint64_t> *Off = 11085ffd83dbSDimitry Andric shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, 11095ffd83dbSDimitry Andric DObj->getFrameSection().Data)) { 11105ffd83dbSDimitry Andric if (Expected<const DWARFDebugFrame *> DF = getDebugFrame()) 1111bdd1243dSDimitry Andric (*DF)->dump(OS, DumpOpts, *Off); 11125ffd83dbSDimitry Andric else 11135ffd83dbSDimitry Andric RecoverableErrorHandler(DF.takeError()); 11140b57cec5SDimitry Andric } 11155ffd83dbSDimitry Andric 1116bdd1243dSDimitry Andric if (const std::optional<uint64_t> *Off = 11175ffd83dbSDimitry Andric shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, 11185ffd83dbSDimitry Andric DObj->getEHFrameSection().Data)) { 11195ffd83dbSDimitry Andric if (Expected<const DWARFDebugFrame *> DF = getEHFrame()) 1120bdd1243dSDimitry Andric (*DF)->dump(OS, DumpOpts, *Off); 11215ffd83dbSDimitry Andric else 11225ffd83dbSDimitry Andric RecoverableErrorHandler(DF.takeError()); 11235ffd83dbSDimitry Andric } 11245ffd83dbSDimitry Andric 11255ffd83dbSDimitry Andric if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro, 11265ffd83dbSDimitry Andric DObj->getMacroSection().Data)) { 11275ffd83dbSDimitry Andric if (auto Macro = getDebugMacro()) 11285ffd83dbSDimitry Andric Macro->dump(OS); 11295ffd83dbSDimitry Andric } 11305ffd83dbSDimitry Andric 11315ffd83dbSDimitry Andric if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro, 11325ffd83dbSDimitry Andric DObj->getMacroDWOSection())) { 11335ffd83dbSDimitry Andric if (auto MacroDWO = getDebugMacroDWO()) 11345ffd83dbSDimitry Andric MacroDWO->dump(OS); 11355ffd83dbSDimitry Andric } 11365ffd83dbSDimitry Andric 11375ffd83dbSDimitry Andric if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro, 11385ffd83dbSDimitry Andric DObj->getMacinfoSection())) { 11395ffd83dbSDimitry Andric if (auto Macinfo = getDebugMacinfo()) 11405ffd83dbSDimitry Andric Macinfo->dump(OS); 11415ffd83dbSDimitry Andric } 11425ffd83dbSDimitry Andric 11435ffd83dbSDimitry Andric if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro, 11445ffd83dbSDimitry Andric DObj->getMacinfoDWOSection())) { 11455ffd83dbSDimitry Andric if (auto MacinfoDWO = getDebugMacinfoDWO()) 11465ffd83dbSDimitry Andric MacinfoDWO->dump(OS); 11470b57cec5SDimitry Andric } 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges, 11508bcb0991SDimitry Andric DObj->getArangesSection())) { 11518bcb0991SDimitry Andric uint64_t offset = 0; 11525ffd83dbSDimitry Andric DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(), 11535ffd83dbSDimitry Andric 0); 11540b57cec5SDimitry Andric DWARFDebugArangeSet set; 11555ffd83dbSDimitry Andric while (arangesData.isValidOffset(offset)) { 1156e8d8bef9SDimitry Andric if (Error E = 1157e8d8bef9SDimitry Andric set.extract(arangesData, &offset, DumpOpts.WarningHandler)) { 11585ffd83dbSDimitry Andric RecoverableErrorHandler(std::move(E)); 11595ffd83dbSDimitry Andric break; 11605ffd83dbSDimitry Andric } 11610b57cec5SDimitry Andric set.dump(OS); 11620b57cec5SDimitry Andric } 11635ffd83dbSDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser, 11660b57cec5SDimitry Andric DIDumpOptions DumpOpts, 1167bdd1243dSDimitry Andric std::optional<uint64_t> DumpOffset) { 11680b57cec5SDimitry Andric while (!Parser.done()) { 11690b57cec5SDimitry Andric if (DumpOffset && Parser.getOffset() != *DumpOffset) { 11705ffd83dbSDimitry Andric Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler); 11710b57cec5SDimitry Andric continue; 11720b57cec5SDimitry Andric } 11738bcb0991SDimitry Andric OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset()) 11748bcb0991SDimitry Andric << "]\n"; 11755ffd83dbSDimitry Andric Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS, 11765ffd83dbSDimitry Andric DumpOpts.Verbose); 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric }; 11790b57cec5SDimitry Andric 1180e8d8bef9SDimitry Andric auto DumpStrSection = [&](StringRef Section) { 1181e8d8bef9SDimitry Andric DataExtractor StrData(Section, isLittleEndian(), 0); 1182e8d8bef9SDimitry Andric uint64_t Offset = 0; 1183e8d8bef9SDimitry Andric uint64_t StrOffset = 0; 1184e8d8bef9SDimitry Andric while (StrData.isValidOffset(Offset)) { 1185e8d8bef9SDimitry Andric Error Err = Error::success(); 1186e8d8bef9SDimitry Andric const char *CStr = StrData.getCStr(&Offset, &Err); 1187e8d8bef9SDimitry Andric if (Err) { 1188e8d8bef9SDimitry Andric DumpOpts.WarningHandler(std::move(Err)); 1189e8d8bef9SDimitry Andric return; 1190e8d8bef9SDimitry Andric } 1191e8d8bef9SDimitry Andric OS << format("0x%8.8" PRIx64 ": \"", StrOffset); 1192e8d8bef9SDimitry Andric OS.write_escaped(CStr); 1193e8d8bef9SDimitry Andric OS << "\"\n"; 1194e8d8bef9SDimitry Andric StrOffset = Offset; 1195e8d8bef9SDimitry Andric } 1196e8d8bef9SDimitry Andric }; 1197e8d8bef9SDimitry Andric 11980b57cec5SDimitry Andric if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine, 11990b57cec5SDimitry Andric DObj->getLineSection().Data)) { 12000b57cec5SDimitry Andric DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(), 12010b57cec5SDimitry Andric 0); 1202e8d8bef9SDimitry Andric DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units()); 12030b57cec5SDimitry Andric DumpLineSection(Parser, DumpOpts, *Off); 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric if (const auto *Off = 12070b57cec5SDimitry Andric shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine, 12080b57cec5SDimitry Andric DObj->getLineDWOSection().Data)) { 12090b57cec5SDimitry Andric DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(), 12100b57cec5SDimitry Andric isLittleEndian(), 0); 1211e8d8bef9SDimitry Andric DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units()); 12120b57cec5SDimitry Andric DumpLineSection(Parser, DumpOpts, *Off); 12130b57cec5SDimitry Andric } 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex, 12160b57cec5SDimitry Andric DObj->getCUIndexSection())) { 12170b57cec5SDimitry Andric getCUIndex().dump(OS); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex, 12210b57cec5SDimitry Andric DObj->getTUIndexSection())) { 12220b57cec5SDimitry Andric getTUIndex().dump(OS); 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr, 1226e8d8bef9SDimitry Andric DObj->getStrSection())) 1227e8d8bef9SDimitry Andric DumpStrSection(DObj->getStrSection()); 1228e8d8bef9SDimitry Andric 12290b57cec5SDimitry Andric if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr, 1230e8d8bef9SDimitry Andric DObj->getStrDWOSection())) 1231e8d8bef9SDimitry Andric DumpStrSection(DObj->getStrDWOSection()); 1232e8d8bef9SDimitry Andric 12330b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr, 1234e8d8bef9SDimitry Andric DObj->getLineStrSection())) 1235e8d8bef9SDimitry Andric DumpStrSection(DObj->getLineStrSection()); 12360b57cec5SDimitry Andric 12370b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr, 12380b57cec5SDimitry Andric DObj->getAddrSection().Data)) { 12390b57cec5SDimitry Andric DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(), 12400b57cec5SDimitry Andric isLittleEndian(), 0); 12410b57cec5SDimitry Andric dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize()); 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, 12458bcb0991SDimitry Andric DObj->getRangesSection().Data)) { 12460b57cec5SDimitry Andric uint8_t savedAddressByteSize = getCUAddrSize(); 12478bcb0991SDimitry Andric DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(), 12480b57cec5SDimitry Andric isLittleEndian(), savedAddressByteSize); 12498bcb0991SDimitry Andric uint64_t offset = 0; 12500b57cec5SDimitry Andric DWARFDebugRangeList rangeList; 12510b57cec5SDimitry Andric while (rangesData.isValidOffset(offset)) { 12520b57cec5SDimitry Andric if (Error E = rangeList.extract(rangesData, &offset)) { 12535ffd83dbSDimitry Andric DumpOpts.RecoverableErrorHandler(std::move(E)); 12540b57cec5SDimitry Andric break; 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric rangeList.dump(OS); 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric 1260bdd1243dSDimitry Andric auto LookupPooledAddress = 1261bdd1243dSDimitry Andric [&](uint32_t Index) -> std::optional<SectionedAddress> { 12620b57cec5SDimitry Andric const auto &CUs = compile_units(); 12630b57cec5SDimitry Andric auto I = CUs.begin(); 12640b57cec5SDimitry Andric if (I == CUs.end()) 1265bdd1243dSDimitry Andric return std::nullopt; 12660b57cec5SDimitry Andric return (*I)->getAddrOffsetSectionItem(Index); 12670b57cec5SDimitry Andric }; 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, 12700b57cec5SDimitry Andric DObj->getRnglistsSection().Data)) { 12710b57cec5SDimitry Andric DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), 12720b57cec5SDimitry Andric isLittleEndian(), 0); 12730b57cec5SDimitry Andric dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); 12740b57cec5SDimitry Andric } 12750b57cec5SDimitry Andric 12760b57cec5SDimitry Andric if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, 12770b57cec5SDimitry Andric DObj->getRnglistsDWOSection().Data)) { 12780b57cec5SDimitry Andric DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), 12790b57cec5SDimitry Andric isLittleEndian(), 0); 12800b57cec5SDimitry Andric dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, 12845ffd83dbSDimitry Andric DObj->getPubnamesSection().Data)) { 12855ffd83dbSDimitry Andric DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(), 12865ffd83dbSDimitry Andric isLittleEndian(), 0); 12875ffd83dbSDimitry Andric dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false); 12885ffd83dbSDimitry Andric } 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes, 12915ffd83dbSDimitry Andric DObj->getPubtypesSection().Data)) { 12925ffd83dbSDimitry Andric DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(), 12935ffd83dbSDimitry Andric isLittleEndian(), 0); 12945ffd83dbSDimitry Andric dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false); 12955ffd83dbSDimitry Andric } 12960b57cec5SDimitry Andric 12970b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames, 12985ffd83dbSDimitry Andric DObj->getGnuPubnamesSection().Data)) { 12995ffd83dbSDimitry Andric DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(), 13005ffd83dbSDimitry Andric isLittleEndian(), 0); 13015ffd83dbSDimitry Andric dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true); 13025ffd83dbSDimitry Andric } 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes, 13055ffd83dbSDimitry Andric DObj->getGnuPubtypesSection().Data)) { 13065ffd83dbSDimitry Andric DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(), 13075ffd83dbSDimitry Andric isLittleEndian(), 0); 13085ffd83dbSDimitry Andric dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true); 13095ffd83dbSDimitry Andric } 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets, 13128bcb0991SDimitry Andric DObj->getStrOffsetsSection().Data)) 13135ffd83dbSDimitry Andric dumpStringOffsetsSection( 13145ffd83dbSDimitry Andric OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(), 13155ffd83dbSDimitry Andric DObj->getStrSection(), normal_units(), isLittleEndian()); 13160b57cec5SDimitry Andric if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, 13178bcb0991SDimitry Andric DObj->getStrOffsetsDWOSection().Data)) 13185ffd83dbSDimitry Andric dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj, 13198bcb0991SDimitry Andric DObj->getStrOffsetsDWOSection(), 13208bcb0991SDimitry Andric DObj->getStrDWOSection(), dwo_units(), 13215ffd83dbSDimitry Andric isLittleEndian()); 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex, 13240b57cec5SDimitry Andric DObj->getGdbIndexSection())) { 13250b57cec5SDimitry Andric getGdbIndex().dump(OS); 13260b57cec5SDimitry Andric } 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames, 13290b57cec5SDimitry Andric DObj->getAppleNamesSection().Data)) 13300b57cec5SDimitry Andric getAppleNames().dump(OS); 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes, 13330b57cec5SDimitry Andric DObj->getAppleTypesSection().Data)) 13340b57cec5SDimitry Andric getAppleTypes().dump(OS); 13350b57cec5SDimitry Andric 13360b57cec5SDimitry Andric if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces, 13370b57cec5SDimitry Andric DObj->getAppleNamespacesSection().Data)) 13380b57cec5SDimitry Andric getAppleNamespaces().dump(OS); 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC, 13410b57cec5SDimitry Andric DObj->getAppleObjCSection().Data)) 13420b57cec5SDimitry Andric getAppleObjC().dump(OS); 13430b57cec5SDimitry Andric if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames, 13448bcb0991SDimitry Andric DObj->getNamesSection().Data)) 13450b57cec5SDimitry Andric getDebugNames().dump(OS); 13460b57cec5SDimitry Andric } 13470b57cec5SDimitry Andric 1348349cc55cSDimitry Andric DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash, 1349349cc55cSDimitry Andric bool IsDWO) { 13505f757f3fSDimitry Andric DWARFUnitVector &DWOUnits = State->getDWOUnits(); 135104eeddc0SDimitry Andric if (const auto &TUI = getTUIndex()) { 135204eeddc0SDimitry Andric if (const auto *R = TUI.getFromHash(Hash)) 135304eeddc0SDimitry Andric return dyn_cast_or_null<DWARFTypeUnit>( 135404eeddc0SDimitry Andric DWOUnits.getUnitForIndexEntry(*R)); 1355349cc55cSDimitry Andric return nullptr; 1356349cc55cSDimitry Andric } 13577a6dacacSDimitry Andric return State->getTypeUnitMap(IsDWO).lookup(Hash); 135804eeddc0SDimitry Andric } 135904eeddc0SDimitry Andric 13600b57cec5SDimitry Andric DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { 13615f757f3fSDimitry Andric DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse); 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric if (const auto &CUI = getCUIndex()) { 13640b57cec5SDimitry Andric if (const auto *R = CUI.getFromHash(Hash)) 13650b57cec5SDimitry Andric return dyn_cast_or_null<DWARFCompileUnit>( 13660b57cec5SDimitry Andric DWOUnits.getUnitForIndexEntry(*R)); 13670b57cec5SDimitry Andric return nullptr; 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric // If there's no index, just search through the CUs in the DWO - there's 13710b57cec5SDimitry Andric // probably only one unless this is something like LTO - though an in-process 13720b57cec5SDimitry Andric // built/cached lookup table could be used in that case to improve repeated 13730b57cec5SDimitry Andric // lookups of different CUs in the DWO. 13740b57cec5SDimitry Andric for (const auto &DWOCU : dwo_compile_units()) { 13750b57cec5SDimitry Andric // Might not have parsed DWO ID yet. 13760b57cec5SDimitry Andric if (!DWOCU->getDWOId()) { 1377bdd1243dSDimitry Andric if (std::optional<uint64_t> DWOId = 13780b57cec5SDimitry Andric toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id))) 13790b57cec5SDimitry Andric DWOCU->setDWOId(*DWOId); 13800b57cec5SDimitry Andric else 13810b57cec5SDimitry Andric // No DWO ID? 13820b57cec5SDimitry Andric continue; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric if (DWOCU->getDWOId() == Hash) 13850b57cec5SDimitry Andric return dyn_cast<DWARFCompileUnit>(DWOCU.get()); 13860b57cec5SDimitry Andric } 13870b57cec5SDimitry Andric return nullptr; 13880b57cec5SDimitry Andric } 13890b57cec5SDimitry Andric 13908bcb0991SDimitry Andric DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) { 13915f757f3fSDimitry Andric if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset)) 13920b57cec5SDimitry Andric return CU->getDIEForOffset(Offset); 13930b57cec5SDimitry Andric return DWARFDie(); 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) { 13970b57cec5SDimitry Andric bool Success = true; 13980b57cec5SDimitry Andric DWARFVerifier verifier(OS, *this, DumpOpts); 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric Success &= verifier.handleDebugAbbrev(); 140181ad6265SDimitry Andric if (DumpOpts.DumpType & DIDT_DebugCUIndex) 140281ad6265SDimitry Andric Success &= verifier.handleDebugCUIndex(); 140381ad6265SDimitry Andric if (DumpOpts.DumpType & DIDT_DebugTUIndex) 140481ad6265SDimitry Andric Success &= verifier.handleDebugTUIndex(); 14050b57cec5SDimitry Andric if (DumpOpts.DumpType & DIDT_DebugInfo) 14060b57cec5SDimitry Andric Success &= verifier.handleDebugInfo(); 14070b57cec5SDimitry Andric if (DumpOpts.DumpType & DIDT_DebugLine) 14080b57cec5SDimitry Andric Success &= verifier.handleDebugLine(); 140906c3fb27SDimitry Andric if (DumpOpts.DumpType & DIDT_DebugStrOffsets) 141006c3fb27SDimitry Andric Success &= verifier.handleDebugStrOffsets(); 14110b57cec5SDimitry Andric Success &= verifier.handleAccelTables(); 1412*0fca6ea1SDimitry Andric verifier.summarize(); 14130b57cec5SDimitry Andric return Success; 14140b57cec5SDimitry Andric } 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric const DWARFUnitIndex &DWARFContext::getCUIndex() { 14175f757f3fSDimitry Andric return State->getCUIndex(); 14180b57cec5SDimitry Andric } 14190b57cec5SDimitry Andric 14200b57cec5SDimitry Andric const DWARFUnitIndex &DWARFContext::getTUIndex() { 14215f757f3fSDimitry Andric return State->getTUIndex(); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andric DWARFGdbIndex &DWARFContext::getGdbIndex() { 14255f757f3fSDimitry Andric return State->getGdbIndex(); 14260b57cec5SDimitry Andric } 14270b57cec5SDimitry Andric 14280b57cec5SDimitry Andric const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { 14295f757f3fSDimitry Andric return State->getDebugAbbrev(); 14300b57cec5SDimitry Andric } 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { 14335f757f3fSDimitry Andric return State->getDebugAbbrevDWO(); 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric const DWARFDebugLoc *DWARFContext::getDebugLoc() { 14375f757f3fSDimitry Andric return State->getDebugLoc(); 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andric const DWARFDebugAranges *DWARFContext::getDebugAranges() { 14415f757f3fSDimitry Andric return State->getDebugAranges(); 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric 14445ffd83dbSDimitry Andric Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() { 14455f757f3fSDimitry Andric return State->getDebugFrame(); 14460b57cec5SDimitry Andric } 14470b57cec5SDimitry Andric 14485ffd83dbSDimitry Andric Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() { 14495f757f3fSDimitry Andric return State->getEHFrame(); 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric 14525ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacro() { 14535f757f3fSDimitry Andric return State->getDebugMacro(); 14545ffd83dbSDimitry Andric } 1455480093f4SDimitry Andric 14565ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() { 14575f757f3fSDimitry Andric return State->getDebugMacroDWO(); 1458480093f4SDimitry Andric } 1459480093f4SDimitry Andric 14605ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacinfo() { 14615f757f3fSDimitry Andric return State->getDebugMacinfo(); 14625ffd83dbSDimitry Andric } 14630b57cec5SDimitry Andric 14645ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() { 14655f757f3fSDimitry Andric return State->getDebugMacinfoDWO(); 14660b57cec5SDimitry Andric } 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric 14690b57cec5SDimitry Andric const DWARFDebugNames &DWARFContext::getDebugNames() { 14705f757f3fSDimitry Andric return State->getDebugNames(); 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleNames() { 14745f757f3fSDimitry Andric return State->getAppleNames(); 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleTypes() { 14785f757f3fSDimitry Andric return State->getAppleTypes(); 14790b57cec5SDimitry Andric } 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() { 14825f757f3fSDimitry Andric return State->getAppleNamespaces(); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleObjC() { 14865f757f3fSDimitry Andric return State->getAppleObjC(); 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric const DWARFDebugLine::LineTable * 14900b57cec5SDimitry Andric DWARFContext::getLineTableForUnit(DWARFUnit *U) { 14910b57cec5SDimitry Andric Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable = 14925ffd83dbSDimitry Andric getLineTableForUnit(U, WarningHandler); 14930b57cec5SDimitry Andric if (!ExpectedLineTable) { 14945ffd83dbSDimitry Andric WarningHandler(ExpectedLineTable.takeError()); 14950b57cec5SDimitry Andric return nullptr; 14960b57cec5SDimitry Andric } 14970b57cec5SDimitry Andric return *ExpectedLineTable; 14980b57cec5SDimitry Andric } 14990b57cec5SDimitry Andric 15000b57cec5SDimitry Andric Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( 15015ffd83dbSDimitry Andric DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) { 15025f757f3fSDimitry Andric return State->getLineTableForUnit(U, RecoverableErrorHandler); 15030b57cec5SDimitry Andric } 15040b57cec5SDimitry Andric 150581ad6265SDimitry Andric void DWARFContext::clearLineTableForUnit(DWARFUnit *U) { 15065f757f3fSDimitry Andric return State->clearLineTableForUnit(U); 150781ad6265SDimitry Andric } 150881ad6265SDimitry Andric 15095f757f3fSDimitry Andric DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) { 15105f757f3fSDimitry Andric return State->getDWOUnits(Lazy); 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric 15138bcb0991SDimitry Andric DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) { 15140b57cec5SDimitry Andric return dyn_cast_or_null<DWARFCompileUnit>( 15155f757f3fSDimitry Andric State->getNormalUnits().getUnitForOffset(Offset)); 15160b57cec5SDimitry Andric } 15170b57cec5SDimitry Andric 151806c3fb27SDimitry Andric DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) { 15198bcb0991SDimitry Andric uint64_t CUOffset = getDebugAranges()->findAddress(Address); 152006c3fb27SDimitry Andric return getCompileUnitForOffset(CUOffset); 152106c3fb27SDimitry Andric } 152206c3fb27SDimitry Andric 152306c3fb27SDimitry Andric DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) { 152406c3fb27SDimitry Andric uint64_t CUOffset = getDebugAranges()->findAddress(Address); 152581ad6265SDimitry Andric if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) 152681ad6265SDimitry Andric return OffsetCU; 152781ad6265SDimitry Andric 152806c3fb27SDimitry Andric // Global variables are often missed by the above search, for one of two 152981ad6265SDimitry Andric // reasons: 153081ad6265SDimitry Andric // 1. .debug_aranges may not include global variables. On clang, it seems we 153181ad6265SDimitry Andric // put the globals in the aranges, but this isn't true for gcc. 153281ad6265SDimitry Andric // 2. Even if the global variable is in a .debug_arange, global variables 153381ad6265SDimitry Andric // may not be captured in the [start, end) addresses described by the 153481ad6265SDimitry Andric // parent compile unit. 153581ad6265SDimitry Andric // 153681ad6265SDimitry Andric // So, we walk the CU's and their child DI's manually, looking for the 153781ad6265SDimitry Andric // specific global variable. 153881ad6265SDimitry Andric for (std::unique_ptr<DWARFUnit> &CU : compile_units()) { 15395f757f3fSDimitry Andric if (CU->getVariableForAddress(Address)) { 154081ad6265SDimitry Andric return static_cast<DWARFCompileUnit *>(CU.get()); 154181ad6265SDimitry Andric } 154281ad6265SDimitry Andric } 154381ad6265SDimitry Andric return nullptr; 15440b57cec5SDimitry Andric } 15450b57cec5SDimitry Andric 15467a6dacacSDimitry Andric DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address, 15477a6dacacSDimitry Andric bool CheckDWO) { 15480b57cec5SDimitry Andric DIEsForAddress Result; 15490b57cec5SDimitry Andric 155006c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address); 15510b57cec5SDimitry Andric if (!CU) 15520b57cec5SDimitry Andric return Result; 15530b57cec5SDimitry Andric 15547a6dacacSDimitry Andric if (CheckDWO) { 15557a6dacacSDimitry Andric // We were asked to check the DWO file and this debug information is more 15567a6dacacSDimitry Andric // complete that any information in the skeleton compile unit, so search the 15577a6dacacSDimitry Andric // DWO first to see if we have a match. 15587a6dacacSDimitry Andric DWARFDie CUDie = CU->getUnitDIE(false); 15597a6dacacSDimitry Andric DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false); 15607a6dacacSDimitry Andric if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) { 15617a6dacacSDimitry Andric // We have a DWO file, lets search it. 15627a6dacacSDimitry Andric DWARFCompileUnit *CUDwo = 15637a6dacacSDimitry Andric dyn_cast_or_null<DWARFCompileUnit>(CUDwoDie.getDwarfUnit()); 15647a6dacacSDimitry Andric if (CUDwo) { 15657a6dacacSDimitry Andric Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address); 15667a6dacacSDimitry Andric if (Result.FunctionDIE) 15677a6dacacSDimitry Andric Result.CompileUnit = CUDwo; 15687a6dacacSDimitry Andric } 15697a6dacacSDimitry Andric } 15707a6dacacSDimitry Andric } 15717a6dacacSDimitry Andric 15727a6dacacSDimitry Andric // Search the normal DWARF if we didn't find a match in the DWO file or if 15737a6dacacSDimitry Andric // we didn't check the DWO file above. 15747a6dacacSDimitry Andric if (!Result) { 15750b57cec5SDimitry Andric Result.CompileUnit = CU; 15760b57cec5SDimitry Andric Result.FunctionDIE = CU->getSubroutineForAddress(Address); 15777a6dacacSDimitry Andric } 15780b57cec5SDimitry Andric 15790b57cec5SDimitry Andric std::vector<DWARFDie> Worklist; 15800b57cec5SDimitry Andric Worklist.push_back(Result.FunctionDIE); 15810b57cec5SDimitry Andric while (!Worklist.empty()) { 15820b57cec5SDimitry Andric DWARFDie DIE = Worklist.back(); 15830b57cec5SDimitry Andric Worklist.pop_back(); 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric if (!DIE.isValid()) 15860b57cec5SDimitry Andric continue; 15870b57cec5SDimitry Andric 15880b57cec5SDimitry Andric if (DIE.getTag() == DW_TAG_lexical_block && 15890b57cec5SDimitry Andric DIE.addressRangeContainsAddress(Address)) { 15900b57cec5SDimitry Andric Result.BlockDIE = DIE; 15910b57cec5SDimitry Andric break; 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric 1594fe6060f1SDimitry Andric append_range(Worklist, DIE); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric return Result; 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric /// TODO: change input parameter from "uint64_t Address" 16010b57cec5SDimitry Andric /// into "SectionedAddress Address" 1602fe6060f1SDimitry Andric static bool getFunctionNameAndStartLineForAddress( 1603fe6060f1SDimitry Andric DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, 1604e8d8bef9SDimitry Andric DILineInfoSpecifier::FileLineInfoKind FileNameKind, 1605fe6060f1SDimitry Andric std::string &FunctionName, std::string &StartFile, uint32_t &StartLine, 1606bdd1243dSDimitry Andric std::optional<uint64_t> &StartAddress) { 16070b57cec5SDimitry Andric // The address may correspond to instruction in some inlined function, 16080b57cec5SDimitry Andric // so we have to build the chain of inlined functions and take the 16090b57cec5SDimitry Andric // name of the topmost function in it. 16100b57cec5SDimitry Andric SmallVector<DWARFDie, 4> InlinedChain; 16110b57cec5SDimitry Andric CU->getInlinedChainForAddress(Address, InlinedChain); 16120b57cec5SDimitry Andric if (InlinedChain.empty()) 16130b57cec5SDimitry Andric return false; 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric const DWARFDie &DIE = InlinedChain[0]; 16160b57cec5SDimitry Andric bool FoundResult = false; 16170b57cec5SDimitry Andric const char *Name = nullptr; 16180b57cec5SDimitry Andric if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) { 16190b57cec5SDimitry Andric FunctionName = Name; 16200b57cec5SDimitry Andric FoundResult = true; 16210b57cec5SDimitry Andric } 1622e8d8bef9SDimitry Andric std::string DeclFile = DIE.getDeclFile(FileNameKind); 1623e8d8bef9SDimitry Andric if (!DeclFile.empty()) { 1624e8d8bef9SDimitry Andric StartFile = DeclFile; 1625e8d8bef9SDimitry Andric FoundResult = true; 1626e8d8bef9SDimitry Andric } 16270b57cec5SDimitry Andric if (auto DeclLineResult = DIE.getDeclLine()) { 16280b57cec5SDimitry Andric StartLine = DeclLineResult; 16290b57cec5SDimitry Andric FoundResult = true; 16300b57cec5SDimitry Andric } 1631fe6060f1SDimitry Andric if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc))) 1632fe6060f1SDimitry Andric StartAddress = LowPcAddr->Address; 16330b57cec5SDimitry Andric return FoundResult; 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric 1636bdd1243dSDimitry Andric static std::optional<int64_t> 1637480093f4SDimitry Andric getExpressionFrameOffset(ArrayRef<uint8_t> Expr, 1638bdd1243dSDimitry Andric std::optional<unsigned> FrameBaseReg) { 1639480093f4SDimitry Andric if (!Expr.empty() && 1640480093f4SDimitry Andric (Expr[0] == DW_OP_fbreg || 1641480093f4SDimitry Andric (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) { 1642480093f4SDimitry Andric unsigned Count; 1643480093f4SDimitry Andric int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end()); 1644480093f4SDimitry Andric // A single DW_OP_fbreg or DW_OP_breg. 1645480093f4SDimitry Andric if (Expr.size() == Count + 1) 1646480093f4SDimitry Andric return Offset; 1647480093f4SDimitry Andric // Same + DW_OP_deref (Fortran arrays look like this). 1648480093f4SDimitry Andric if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref) 1649480093f4SDimitry Andric return Offset; 1650480093f4SDimitry Andric // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value) 1651480093f4SDimitry Andric } 1652bdd1243dSDimitry Andric return std::nullopt; 1653480093f4SDimitry Andric } 1654480093f4SDimitry Andric 16550b57cec5SDimitry Andric void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, 16560b57cec5SDimitry Andric DWARFDie Die, std::vector<DILocal> &Result) { 16570b57cec5SDimitry Andric if (Die.getTag() == DW_TAG_variable || 16580b57cec5SDimitry Andric Die.getTag() == DW_TAG_formal_parameter) { 16590b57cec5SDimitry Andric DILocal Local; 1660480093f4SDimitry Andric if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName)) 1661480093f4SDimitry Andric Local.FunctionName = Name; 1662480093f4SDimitry Andric 1663bdd1243dSDimitry Andric std::optional<unsigned> FrameBaseReg; 1664480093f4SDimitry Andric if (auto FrameBase = Subprogram.find(DW_AT_frame_base)) 1665bdd1243dSDimitry Andric if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock()) 1666480093f4SDimitry Andric if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 && 1667480093f4SDimitry Andric (*Expr)[0] <= DW_OP_reg31) { 1668480093f4SDimitry Andric FrameBaseReg = (*Expr)[0] - DW_OP_reg0; 1669480093f4SDimitry Andric } 1670480093f4SDimitry Andric 1671480093f4SDimitry Andric if (Expected<std::vector<DWARFLocationExpression>> Loc = 1672480093f4SDimitry Andric Die.getLocations(DW_AT_location)) { 1673480093f4SDimitry Andric for (const auto &Entry : *Loc) { 1674bdd1243dSDimitry Andric if (std::optional<int64_t> FrameOffset = 1675480093f4SDimitry Andric getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) { 1676480093f4SDimitry Andric Local.FrameOffset = *FrameOffset; 1677480093f4SDimitry Andric break; 1678480093f4SDimitry Andric } 1679480093f4SDimitry Andric } 1680480093f4SDimitry Andric } else { 1681480093f4SDimitry Andric // FIXME: missing DW_AT_location is OK here, but other errors should be 1682480093f4SDimitry Andric // reported to the user. 1683480093f4SDimitry Andric consumeError(Loc.takeError()); 1684480093f4SDimitry Andric } 1685480093f4SDimitry Andric 16860b57cec5SDimitry Andric if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) 16870b57cec5SDimitry Andric Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric if (auto Origin = 16900b57cec5SDimitry Andric Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 16910b57cec5SDimitry Andric Die = Origin; 16920b57cec5SDimitry Andric if (auto NameAttr = Die.find(DW_AT_name)) 1693bdd1243dSDimitry Andric if (std::optional<const char *> Name = dwarf::toString(*NameAttr)) 16940b57cec5SDimitry Andric Local.Name = *Name; 16950b57cec5SDimitry Andric if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) 169681ad6265SDimitry Andric Local.Size = Type.getTypeSize(getCUAddrSize()); 16970b57cec5SDimitry Andric if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { 16980b57cec5SDimitry Andric if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) 16990b57cec5SDimitry Andric LT->getFileNameByIndex( 1700bdd1243dSDimitry Andric *DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(), 17010b57cec5SDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 17020b57cec5SDimitry Andric Local.DeclFile); 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric if (auto DeclLineAttr = Die.find(DW_AT_decl_line)) 1705bdd1243dSDimitry Andric Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant(); 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric Result.push_back(Local); 17080b57cec5SDimitry Andric return; 17090b57cec5SDimitry Andric } 17100b57cec5SDimitry Andric 17110b57cec5SDimitry Andric if (Die.getTag() == DW_TAG_inlined_subroutine) 17120b57cec5SDimitry Andric if (auto Origin = 17130b57cec5SDimitry Andric Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 17140b57cec5SDimitry Andric Subprogram = Origin; 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric for (auto Child : Die) 17170b57cec5SDimitry Andric addLocalsForDie(CU, Subprogram, Child, Result); 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric std::vector<DILocal> 17210b57cec5SDimitry Andric DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { 17220b57cec5SDimitry Andric std::vector<DILocal> Result; 172306c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); 17240b57cec5SDimitry Andric if (!CU) 17250b57cec5SDimitry Andric return Result; 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address); 17280b57cec5SDimitry Andric if (Subprogram.isValid()) 17290b57cec5SDimitry Andric addLocalsForDie(CU, Subprogram, Subprogram, Result); 17300b57cec5SDimitry Andric return Result; 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, 17340b57cec5SDimitry Andric DILineInfoSpecifier Spec) { 17350b57cec5SDimitry Andric DILineInfo Result; 173606c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); 17370b57cec5SDimitry Andric if (!CU) 17380b57cec5SDimitry Andric return Result; 17390b57cec5SDimitry Andric 1740fe6060f1SDimitry Andric getFunctionNameAndStartLineForAddress( 1741fe6060f1SDimitry Andric CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName, 1742fe6060f1SDimitry Andric Result.StartFileName, Result.StartLine, Result.StartAddress); 17430b57cec5SDimitry Andric if (Spec.FLIKind != FileLineInfoKind::None) { 17440b57cec5SDimitry Andric if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { 17450b57cec5SDimitry Andric LineTable->getFileLineInfoForAddress( 17460b57cec5SDimitry Andric {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), 17470b57cec5SDimitry Andric Spec.FLIKind, Result); 17480b57cec5SDimitry Andric } 17490b57cec5SDimitry Andric } 175081ad6265SDimitry Andric 175181ad6265SDimitry Andric return Result; 175281ad6265SDimitry Andric } 175381ad6265SDimitry Andric 175481ad6265SDimitry Andric DILineInfo 175581ad6265SDimitry Andric DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { 175681ad6265SDimitry Andric DILineInfo Result; 175706c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address); 175881ad6265SDimitry Andric if (!CU) 175981ad6265SDimitry Andric return Result; 176081ad6265SDimitry Andric 176181ad6265SDimitry Andric if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) { 176281ad6265SDimitry Andric Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath); 176381ad6265SDimitry Andric Result.Line = Die.getDeclLine(); 176481ad6265SDimitry Andric } 176581ad6265SDimitry Andric 17660b57cec5SDimitry Andric return Result; 17670b57cec5SDimitry Andric } 17680b57cec5SDimitry Andric 17690b57cec5SDimitry Andric DILineInfoTable DWARFContext::getLineInfoForAddressRange( 17700b57cec5SDimitry Andric object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { 17710b57cec5SDimitry Andric DILineInfoTable Lines; 177206c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); 17730b57cec5SDimitry Andric if (!CU) 17740b57cec5SDimitry Andric return Lines; 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric uint32_t StartLine = 0; 1777e8d8bef9SDimitry Andric std::string StartFileName; 17788bcb0991SDimitry Andric std::string FunctionName(DILineInfo::BadString); 1779bdd1243dSDimitry Andric std::optional<uint64_t> StartAddress; 1780fe6060f1SDimitry Andric getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, 1781fe6060f1SDimitry Andric Spec.FLIKind, FunctionName, 1782fe6060f1SDimitry Andric StartFileName, StartLine, StartAddress); 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric // If the Specifier says we don't need FileLineInfo, just 17850b57cec5SDimitry Andric // return the top-most function at the starting address. 17860b57cec5SDimitry Andric if (Spec.FLIKind == FileLineInfoKind::None) { 17870b57cec5SDimitry Andric DILineInfo Result; 17880b57cec5SDimitry Andric Result.FunctionName = FunctionName; 1789e8d8bef9SDimitry Andric Result.StartFileName = StartFileName; 17900b57cec5SDimitry Andric Result.StartLine = StartLine; 1791fe6060f1SDimitry Andric Result.StartAddress = StartAddress; 17920b57cec5SDimitry Andric Lines.push_back(std::make_pair(Address.Address, Result)); 17930b57cec5SDimitry Andric return Lines; 17940b57cec5SDimitry Andric } 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric const DWARFLineTable *LineTable = getLineTableForUnit(CU); 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric // Get the index of row we're looking for in the line table. 17990b57cec5SDimitry Andric std::vector<uint32_t> RowVector; 18000b57cec5SDimitry Andric if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex}, 18010b57cec5SDimitry Andric Size, RowVector)) { 18020b57cec5SDimitry Andric return Lines; 18030b57cec5SDimitry Andric } 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric for (uint32_t RowIndex : RowVector) { 18060b57cec5SDimitry Andric // Take file number and line/column from the row. 18070b57cec5SDimitry Andric const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; 18080b57cec5SDimitry Andric DILineInfo Result; 18090b57cec5SDimitry Andric LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(), 18100b57cec5SDimitry Andric Spec.FLIKind, Result.FileName); 18110b57cec5SDimitry Andric Result.FunctionName = FunctionName; 18120b57cec5SDimitry Andric Result.Line = Row.Line; 18130b57cec5SDimitry Andric Result.Column = Row.Column; 1814e8d8bef9SDimitry Andric Result.StartFileName = StartFileName; 18150b57cec5SDimitry Andric Result.StartLine = StartLine; 1816fe6060f1SDimitry Andric Result.StartAddress = StartAddress; 18170b57cec5SDimitry Andric Lines.push_back(std::make_pair(Row.Address.Address, Result)); 18180b57cec5SDimitry Andric } 18190b57cec5SDimitry Andric 18200b57cec5SDimitry Andric return Lines; 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 18230b57cec5SDimitry Andric DIInliningInfo 18240b57cec5SDimitry Andric DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, 18250b57cec5SDimitry Andric DILineInfoSpecifier Spec) { 18260b57cec5SDimitry Andric DIInliningInfo InliningInfo; 18270b57cec5SDimitry Andric 182806c3fb27SDimitry Andric DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address); 18290b57cec5SDimitry Andric if (!CU) 18300b57cec5SDimitry Andric return InliningInfo; 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric const DWARFLineTable *LineTable = nullptr; 18330b57cec5SDimitry Andric SmallVector<DWARFDie, 4> InlinedChain; 18340b57cec5SDimitry Andric CU->getInlinedChainForAddress(Address.Address, InlinedChain); 18350b57cec5SDimitry Andric if (InlinedChain.size() == 0) { 18360b57cec5SDimitry Andric // If there is no DIE for address (e.g. it is in unavailable .dwo file), 18370b57cec5SDimitry Andric // try to at least get file/line info from symbol table. 18380b57cec5SDimitry Andric if (Spec.FLIKind != FileLineInfoKind::None) { 18390b57cec5SDimitry Andric DILineInfo Frame; 18400b57cec5SDimitry Andric LineTable = getLineTableForUnit(CU); 18410b57cec5SDimitry Andric if (LineTable && LineTable->getFileLineInfoForAddress( 18420b57cec5SDimitry Andric {Address.Address, Address.SectionIndex}, 18430b57cec5SDimitry Andric CU->getCompilationDir(), Spec.FLIKind, Frame)) 18440b57cec5SDimitry Andric InliningInfo.addFrame(Frame); 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric return InliningInfo; 18470b57cec5SDimitry Andric } 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0; 18500b57cec5SDimitry Andric for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { 18510b57cec5SDimitry Andric DWARFDie &FunctionDIE = InlinedChain[i]; 18520b57cec5SDimitry Andric DILineInfo Frame; 18530b57cec5SDimitry Andric // Get function name if necessary. 18540b57cec5SDimitry Andric if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind)) 18550b57cec5SDimitry Andric Frame.FunctionName = Name; 18560b57cec5SDimitry Andric if (auto DeclLineResult = FunctionDIE.getDeclLine()) 18570b57cec5SDimitry Andric Frame.StartLine = DeclLineResult; 1858e8d8bef9SDimitry Andric Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind); 1859fe6060f1SDimitry Andric if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc))) 1860fe6060f1SDimitry Andric Frame.StartAddress = LowPcAddr->Address; 18610b57cec5SDimitry Andric if (Spec.FLIKind != FileLineInfoKind::None) { 18620b57cec5SDimitry Andric if (i == 0) { 18630b57cec5SDimitry Andric // For the topmost frame, initialize the line table of this 18640b57cec5SDimitry Andric // compile unit and fetch file/line info from it. 18650b57cec5SDimitry Andric LineTable = getLineTableForUnit(CU); 18660b57cec5SDimitry Andric // For the topmost routine, get file/line info from line table. 18670b57cec5SDimitry Andric if (LineTable) 18680b57cec5SDimitry Andric LineTable->getFileLineInfoForAddress( 18690b57cec5SDimitry Andric {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), 18700b57cec5SDimitry Andric Spec.FLIKind, Frame); 18710b57cec5SDimitry Andric } else { 18720b57cec5SDimitry Andric // Otherwise, use call file, call line and call column from 18730b57cec5SDimitry Andric // previous DIE in inlined chain. 18740b57cec5SDimitry Andric if (LineTable) 18750b57cec5SDimitry Andric LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(), 18760b57cec5SDimitry Andric Spec.FLIKind, Frame.FileName); 18770b57cec5SDimitry Andric Frame.Line = CallLine; 18780b57cec5SDimitry Andric Frame.Column = CallColumn; 18790b57cec5SDimitry Andric Frame.Discriminator = CallDiscriminator; 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric // Get call file/line/column of a current DIE. 18820b57cec5SDimitry Andric if (i + 1 < n) { 18830b57cec5SDimitry Andric FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn, 18840b57cec5SDimitry Andric CallDiscriminator); 18850b57cec5SDimitry Andric } 18860b57cec5SDimitry Andric } 18870b57cec5SDimitry Andric InliningInfo.addFrame(Frame); 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric return InliningInfo; 18900b57cec5SDimitry Andric } 18910b57cec5SDimitry Andric 18920b57cec5SDimitry Andric std::shared_ptr<DWARFContext> 18930b57cec5SDimitry Andric DWARFContext::getDWOContext(StringRef AbsolutePath) { 18945f757f3fSDimitry Andric return State->getDWOContext(AbsolutePath); 18950b57cec5SDimitry Andric } 18960b57cec5SDimitry Andric 18970b57cec5SDimitry Andric static Error createError(const Twine &Reason, llvm::Error E) { 18980b57cec5SDimitry Andric return make_error<StringError>(Reason + toString(std::move(E)), 18990b57cec5SDimitry Andric inconvertibleErrorCode()); 19000b57cec5SDimitry Andric } 19010b57cec5SDimitry Andric 19020b57cec5SDimitry Andric /// SymInfo contains information about symbol: it's address 19030b57cec5SDimitry Andric /// and section index which is -1LL for absolute symbols. 19040b57cec5SDimitry Andric struct SymInfo { 19050b57cec5SDimitry Andric uint64_t Address; 19060b57cec5SDimitry Andric uint64_t SectionIndex; 19070b57cec5SDimitry Andric }; 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric /// Returns the address of symbol relocation used against and a section index. 19100b57cec5SDimitry Andric /// Used for futher relocations computation. Symbol's section load address is 19110b57cec5SDimitry Andric static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj, 19120b57cec5SDimitry Andric const RelocationRef &Reloc, 19130b57cec5SDimitry Andric const LoadedObjectInfo *L, 19140b57cec5SDimitry Andric std::map<SymbolRef, SymInfo> &Cache) { 19150b57cec5SDimitry Andric SymInfo Ret = {0, (uint64_t)-1LL}; 19160b57cec5SDimitry Andric object::section_iterator RSec = Obj.section_end(); 19170b57cec5SDimitry Andric object::symbol_iterator Sym = Reloc.getSymbol(); 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end(); 19200b57cec5SDimitry Andric // First calculate the address of the symbol or section as it appears 19210b57cec5SDimitry Andric // in the object file 19220b57cec5SDimitry Andric if (Sym != Obj.symbol_end()) { 19230b57cec5SDimitry Andric bool New; 19240b57cec5SDimitry Andric std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}}); 19250b57cec5SDimitry Andric if (!New) 19260b57cec5SDimitry Andric return CacheIt->second; 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric Expected<uint64_t> SymAddrOrErr = Sym->getAddress(); 19290b57cec5SDimitry Andric if (!SymAddrOrErr) 19300b57cec5SDimitry Andric return createError("failed to compute symbol address: ", 19310b57cec5SDimitry Andric SymAddrOrErr.takeError()); 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric // Also remember what section this symbol is in for later 19340b57cec5SDimitry Andric auto SectOrErr = Sym->getSection(); 19350b57cec5SDimitry Andric if (!SectOrErr) 19360b57cec5SDimitry Andric return createError("failed to get symbol section: ", 19370b57cec5SDimitry Andric SectOrErr.takeError()); 19380b57cec5SDimitry Andric 19390b57cec5SDimitry Andric RSec = *SectOrErr; 19400b57cec5SDimitry Andric Ret.Address = *SymAddrOrErr; 19410b57cec5SDimitry Andric } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) { 19420b57cec5SDimitry Andric RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl()); 19430b57cec5SDimitry Andric Ret.Address = RSec->getAddress(); 19440b57cec5SDimitry Andric } 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric if (RSec != Obj.section_end()) 19470b57cec5SDimitry Andric Ret.SectionIndex = RSec->getIndex(); 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric // If we are given load addresses for the sections, we need to adjust: 19500b57cec5SDimitry Andric // SymAddr = (Address of Symbol Or Section in File) - 19510b57cec5SDimitry Andric // (Address of Section in File) + 19520b57cec5SDimitry Andric // (Load Address of Section) 19530b57cec5SDimitry Andric // RSec is now either the section being targeted or the section 19540b57cec5SDimitry Andric // containing the symbol being targeted. In either case, 19550b57cec5SDimitry Andric // we need to perform the same computation. 19560b57cec5SDimitry Andric if (L && RSec != Obj.section_end()) 19570b57cec5SDimitry Andric if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec)) 19580b57cec5SDimitry Andric Ret.Address += SectionLoadAddress - RSec->getAddress(); 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric if (CacheIt != Cache.end()) 19610b57cec5SDimitry Andric CacheIt->second = Ret; 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric return Ret; 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric static bool isRelocScattered(const object::ObjectFile &Obj, 19670b57cec5SDimitry Andric const RelocationRef &Reloc) { 19680b57cec5SDimitry Andric const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj); 19690b57cec5SDimitry Andric if (!MachObj) 19700b57cec5SDimitry Andric return false; 19710b57cec5SDimitry Andric // MachO also has relocations that point to sections and 19720b57cec5SDimitry Andric // scattered relocations. 19730b57cec5SDimitry Andric auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl()); 19740b57cec5SDimitry Andric return MachObj->isRelocationScattered(RelocInfo); 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 19770b57cec5SDimitry Andric namespace { 19780b57cec5SDimitry Andric struct DWARFSectionMap final : public DWARFSection { 19790b57cec5SDimitry Andric RelocAddrMap Relocs; 19800b57cec5SDimitry Andric }; 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric class DWARFObjInMemory final : public DWARFObject { 19830b57cec5SDimitry Andric bool IsLittleEndian; 19840b57cec5SDimitry Andric uint8_t AddressSize; 19850b57cec5SDimitry Andric StringRef FileName; 19860b57cec5SDimitry Andric const object::ObjectFile *Obj = nullptr; 19870b57cec5SDimitry Andric std::vector<SectionName> SectionNames; 19880b57cec5SDimitry Andric 19890b57cec5SDimitry Andric using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap, 19900b57cec5SDimitry Andric std::map<object::SectionRef, unsigned>>; 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric InfoSectionMap InfoSections; 19930b57cec5SDimitry Andric InfoSectionMap TypesSections; 19940b57cec5SDimitry Andric InfoSectionMap InfoDWOSections; 19950b57cec5SDimitry Andric InfoSectionMap TypesDWOSections; 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric DWARFSectionMap LocSection; 19988bcb0991SDimitry Andric DWARFSectionMap LoclistsSection; 1999480093f4SDimitry Andric DWARFSectionMap LoclistsDWOSection; 20000b57cec5SDimitry Andric DWARFSectionMap LineSection; 20018bcb0991SDimitry Andric DWARFSectionMap RangesSection; 20020b57cec5SDimitry Andric DWARFSectionMap RnglistsSection; 20038bcb0991SDimitry Andric DWARFSectionMap StrOffsetsSection; 20040b57cec5SDimitry Andric DWARFSectionMap LineDWOSection; 20058bcb0991SDimitry Andric DWARFSectionMap FrameSection; 20060b57cec5SDimitry Andric DWARFSectionMap EHFrameSection; 20070b57cec5SDimitry Andric DWARFSectionMap LocDWOSection; 20088bcb0991SDimitry Andric DWARFSectionMap StrOffsetsDWOSection; 20098bcb0991SDimitry Andric DWARFSectionMap RangesDWOSection; 20100b57cec5SDimitry Andric DWARFSectionMap RnglistsDWOSection; 20110b57cec5SDimitry Andric DWARFSectionMap AddrSection; 20120b57cec5SDimitry Andric DWARFSectionMap AppleNamesSection; 20130b57cec5SDimitry Andric DWARFSectionMap AppleTypesSection; 20140b57cec5SDimitry Andric DWARFSectionMap AppleNamespacesSection; 20150b57cec5SDimitry Andric DWARFSectionMap AppleObjCSection; 20168bcb0991SDimitry Andric DWARFSectionMap NamesSection; 20178bcb0991SDimitry Andric DWARFSectionMap PubnamesSection; 20188bcb0991SDimitry Andric DWARFSectionMap PubtypesSection; 20198bcb0991SDimitry Andric DWARFSectionMap GnuPubnamesSection; 20208bcb0991SDimitry Andric DWARFSectionMap GnuPubtypesSection; 20215ffd83dbSDimitry Andric DWARFSectionMap MacroSection; 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { 20240b57cec5SDimitry Andric return StringSwitch<DWARFSectionMap *>(Name) 20250b57cec5SDimitry Andric .Case("debug_loc", &LocSection) 20268bcb0991SDimitry Andric .Case("debug_loclists", &LoclistsSection) 2027480093f4SDimitry Andric .Case("debug_loclists.dwo", &LoclistsDWOSection) 20280b57cec5SDimitry Andric .Case("debug_line", &LineSection) 20298bcb0991SDimitry Andric .Case("debug_frame", &FrameSection) 20300b57cec5SDimitry Andric .Case("eh_frame", &EHFrameSection) 20318bcb0991SDimitry Andric .Case("debug_str_offsets", &StrOffsetsSection) 20328bcb0991SDimitry Andric .Case("debug_ranges", &RangesSection) 20330b57cec5SDimitry Andric .Case("debug_rnglists", &RnglistsSection) 20340b57cec5SDimitry Andric .Case("debug_loc.dwo", &LocDWOSection) 20350b57cec5SDimitry Andric .Case("debug_line.dwo", &LineDWOSection) 20368bcb0991SDimitry Andric .Case("debug_names", &NamesSection) 20370b57cec5SDimitry Andric .Case("debug_rnglists.dwo", &RnglistsDWOSection) 20388bcb0991SDimitry Andric .Case("debug_str_offsets.dwo", &StrOffsetsDWOSection) 20390b57cec5SDimitry Andric .Case("debug_addr", &AddrSection) 20400b57cec5SDimitry Andric .Case("apple_names", &AppleNamesSection) 20418bcb0991SDimitry Andric .Case("debug_pubnames", &PubnamesSection) 20428bcb0991SDimitry Andric .Case("debug_pubtypes", &PubtypesSection) 20438bcb0991SDimitry Andric .Case("debug_gnu_pubnames", &GnuPubnamesSection) 20448bcb0991SDimitry Andric .Case("debug_gnu_pubtypes", &GnuPubtypesSection) 20450b57cec5SDimitry Andric .Case("apple_types", &AppleTypesSection) 20460b57cec5SDimitry Andric .Case("apple_namespaces", &AppleNamespacesSection) 20470b57cec5SDimitry Andric .Case("apple_namespac", &AppleNamespacesSection) 20480b57cec5SDimitry Andric .Case("apple_objc", &AppleObjCSection) 20495ffd83dbSDimitry Andric .Case("debug_macro", &MacroSection) 20500b57cec5SDimitry Andric .Default(nullptr); 20510b57cec5SDimitry Andric } 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric StringRef AbbrevSection; 20548bcb0991SDimitry Andric StringRef ArangesSection; 20558bcb0991SDimitry Andric StringRef StrSection; 20560b57cec5SDimitry Andric StringRef MacinfoSection; 2057480093f4SDimitry Andric StringRef MacinfoDWOSection; 20585ffd83dbSDimitry Andric StringRef MacroDWOSection; 20590b57cec5SDimitry Andric StringRef AbbrevDWOSection; 20608bcb0991SDimitry Andric StringRef StrDWOSection; 20610b57cec5SDimitry Andric StringRef CUIndexSection; 20620b57cec5SDimitry Andric StringRef GdbIndexSection; 20630b57cec5SDimitry Andric StringRef TUIndexSection; 20648bcb0991SDimitry Andric StringRef LineStrSection; 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric // A deque holding section data whose iterators are not invalidated when 20670b57cec5SDimitry Andric // new decompressed sections are inserted at the end. 20680b57cec5SDimitry Andric std::deque<SmallString<0>> UncompressedSections; 20690b57cec5SDimitry Andric 20700b57cec5SDimitry Andric StringRef *mapSectionToMember(StringRef Name) { 20710b57cec5SDimitry Andric if (DWARFSection *Sec = mapNameToDWARFSection(Name)) 20720b57cec5SDimitry Andric return &Sec->Data; 20730b57cec5SDimitry Andric return StringSwitch<StringRef *>(Name) 20740b57cec5SDimitry Andric .Case("debug_abbrev", &AbbrevSection) 20758bcb0991SDimitry Andric .Case("debug_aranges", &ArangesSection) 20768bcb0991SDimitry Andric .Case("debug_str", &StrSection) 20770b57cec5SDimitry Andric .Case("debug_macinfo", &MacinfoSection) 2078480093f4SDimitry Andric .Case("debug_macinfo.dwo", &MacinfoDWOSection) 20795ffd83dbSDimitry Andric .Case("debug_macro.dwo", &MacroDWOSection) 20800b57cec5SDimitry Andric .Case("debug_abbrev.dwo", &AbbrevDWOSection) 20818bcb0991SDimitry Andric .Case("debug_str.dwo", &StrDWOSection) 20820b57cec5SDimitry Andric .Case("debug_cu_index", &CUIndexSection) 20830b57cec5SDimitry Andric .Case("debug_tu_index", &TUIndexSection) 20840b57cec5SDimitry Andric .Case("gdb_index", &GdbIndexSection) 20858bcb0991SDimitry Andric .Case("debug_line_str", &LineStrSection) 20860b57cec5SDimitry Andric // Any more debug info sections go here. 20870b57cec5SDimitry Andric .Default(nullptr); 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric /// If Sec is compressed section, decompresses and updates its contents 20910b57cec5SDimitry Andric /// provided by Data. Otherwise leaves it unchanged. 20920b57cec5SDimitry Andric Error maybeDecompress(const object::SectionRef &Sec, StringRef Name, 20930b57cec5SDimitry Andric StringRef &Data) { 2094fcaf7f86SDimitry Andric if (!Sec.isCompressed()) 20950b57cec5SDimitry Andric return Error::success(); 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric Expected<Decompressor> Decompressor = 20980b57cec5SDimitry Andric Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8); 20990b57cec5SDimitry Andric if (!Decompressor) 21000b57cec5SDimitry Andric return Decompressor.takeError(); 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric SmallString<0> Out; 21030b57cec5SDimitry Andric if (auto Err = Decompressor->resizeAndDecompress(Out)) 21040b57cec5SDimitry Andric return Err; 21050b57cec5SDimitry Andric 21060b57cec5SDimitry Andric UncompressedSections.push_back(std::move(Out)); 21070b57cec5SDimitry Andric Data = UncompressedSections.back(); 21080b57cec5SDimitry Andric 21090b57cec5SDimitry Andric return Error::success(); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 21120b57cec5SDimitry Andric public: 21130b57cec5SDimitry Andric DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 21140b57cec5SDimitry Andric uint8_t AddrSize, bool IsLittleEndian) 21150b57cec5SDimitry Andric : IsLittleEndian(IsLittleEndian) { 21160b57cec5SDimitry Andric for (const auto &SecIt : Sections) { 21170b57cec5SDimitry Andric if (StringRef *SectionData = mapSectionToMember(SecIt.first())) 21180b57cec5SDimitry Andric *SectionData = SecIt.second->getBuffer(); 21190b57cec5SDimitry Andric else if (SecIt.first() == "debug_info") 21200b57cec5SDimitry Andric // Find debug_info and debug_types data by section rather than name as 21210b57cec5SDimitry Andric // there are multiple, comdat grouped, of these sections. 21220b57cec5SDimitry Andric InfoSections[SectionRef()].Data = SecIt.second->getBuffer(); 21230b57cec5SDimitry Andric else if (SecIt.first() == "debug_info.dwo") 21240b57cec5SDimitry Andric InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); 21250b57cec5SDimitry Andric else if (SecIt.first() == "debug_types") 21260b57cec5SDimitry Andric TypesSections[SectionRef()].Data = SecIt.second->getBuffer(); 21270b57cec5SDimitry Andric else if (SecIt.first() == "debug_types.dwo") 21280b57cec5SDimitry Andric TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); 21290b57cec5SDimitry Andric } 21300b57cec5SDimitry Andric } 21310b57cec5SDimitry Andric DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, 2132349cc55cSDimitry Andric function_ref<void(Error)> HandleError, 2133349cc55cSDimitry Andric function_ref<void(Error)> HandleWarning, 2134349cc55cSDimitry Andric DWARFContext::ProcessDebugRelocations RelocAction) 21350b57cec5SDimitry Andric : IsLittleEndian(Obj.isLittleEndian()), 21360b57cec5SDimitry Andric AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()), 21370b57cec5SDimitry Andric Obj(&Obj) { 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric StringMap<unsigned> SectionAmountMap; 21400b57cec5SDimitry Andric for (const SectionRef &Section : Obj.sections()) { 21410b57cec5SDimitry Andric StringRef Name; 21428bcb0991SDimitry Andric if (auto NameOrErr = Section.getName()) 21438bcb0991SDimitry Andric Name = *NameOrErr; 21448bcb0991SDimitry Andric else 21458bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 21468bcb0991SDimitry Andric 21470b57cec5SDimitry Andric ++SectionAmountMap[Name]; 21480b57cec5SDimitry Andric SectionNames.push_back({ Name, true }); 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric // Skip BSS and Virtual sections, they aren't interesting. 21510b57cec5SDimitry Andric if (Section.isBSS() || Section.isVirtual()) 21520b57cec5SDimitry Andric continue; 21530b57cec5SDimitry Andric 21540b57cec5SDimitry Andric // Skip sections stripped by dsymutil. 21550b57cec5SDimitry Andric if (Section.isStripped()) 21560b57cec5SDimitry Andric continue; 21570b57cec5SDimitry Andric 21580b57cec5SDimitry Andric StringRef Data; 21598bcb0991SDimitry Andric Expected<section_iterator> SecOrErr = Section.getRelocatedSection(); 21608bcb0991SDimitry Andric if (!SecOrErr) { 21615ffd83dbSDimitry Andric HandleError(createError("failed to get relocated section: ", 21625ffd83dbSDimitry Andric SecOrErr.takeError())); 21638bcb0991SDimitry Andric continue; 21648bcb0991SDimitry Andric } 21658bcb0991SDimitry Andric 21660b57cec5SDimitry Andric // Try to obtain an already relocated version of this section. 21670b57cec5SDimitry Andric // Else use the unrelocated section from the object file. We'll have to 21680b57cec5SDimitry Andric // apply relocations ourselves later. 2169fe6060f1SDimitry Andric section_iterator RelocatedSection = 2170fe6060f1SDimitry Andric Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end(); 21710b57cec5SDimitry Andric if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { 21720b57cec5SDimitry Andric Expected<StringRef> E = Section.getContents(); 21730b57cec5SDimitry Andric if (E) 21740b57cec5SDimitry Andric Data = *E; 21750b57cec5SDimitry Andric else 21760b57cec5SDimitry Andric // maybeDecompress below will error. 21770b57cec5SDimitry Andric consumeError(E.takeError()); 21780b57cec5SDimitry Andric } 21790b57cec5SDimitry Andric 21800b57cec5SDimitry Andric if (auto Err = maybeDecompress(Section, Name, Data)) { 21815ffd83dbSDimitry Andric HandleError(createError("failed to decompress '" + Name + "', ", 21825ffd83dbSDimitry Andric std::move(Err))); 21830b57cec5SDimitry Andric continue; 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric // Map platform specific debug section names to DWARF standard section 21870b57cec5SDimitry Andric // names. 218806c3fb27SDimitry Andric Name = Name.substr(Name.find_first_not_of("._")); 21890b57cec5SDimitry Andric Name = Obj.mapDebugSectionName(Name); 21900b57cec5SDimitry Andric 21910b57cec5SDimitry Andric if (StringRef *SectionData = mapSectionToMember(Name)) { 21920b57cec5SDimitry Andric *SectionData = Data; 21930b57cec5SDimitry Andric if (Name == "debug_ranges") { 21940b57cec5SDimitry Andric // FIXME: Use the other dwo range section when we emit it. 21958bcb0991SDimitry Andric RangesDWOSection.Data = Data; 2196fe6060f1SDimitry Andric } else if (Name == "debug_frame" || Name == "eh_frame") { 2197fe6060f1SDimitry Andric if (DWARFSection *S = mapNameToDWARFSection(Name)) 2198fe6060f1SDimitry Andric S->Address = Section.getAddress(); 21990b57cec5SDimitry Andric } 2200e8d8bef9SDimitry Andric } else if (InfoSectionMap *Sections = 2201e8d8bef9SDimitry Andric StringSwitch<InfoSectionMap *>(Name) 2202e8d8bef9SDimitry Andric .Case("debug_info", &InfoSections) 2203e8d8bef9SDimitry Andric .Case("debug_info.dwo", &InfoDWOSections) 2204e8d8bef9SDimitry Andric .Case("debug_types", &TypesSections) 2205e8d8bef9SDimitry Andric .Case("debug_types.dwo", &TypesDWOSections) 2206e8d8bef9SDimitry Andric .Default(nullptr)) { 22070b57cec5SDimitry Andric // Find debug_info and debug_types data by section rather than name as 22080b57cec5SDimitry Andric // there are multiple, comdat grouped, of these sections. 2209e8d8bef9SDimitry Andric DWARFSectionMap &S = (*Sections)[Section]; 2210e8d8bef9SDimitry Andric S.Data = Data; 22110b57cec5SDimitry Andric } 22120b57cec5SDimitry Andric 2213349cc55cSDimitry Andric if (RelocatedSection == Obj.section_end() || 2214349cc55cSDimitry Andric (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore)) 22150b57cec5SDimitry Andric continue; 22160b57cec5SDimitry Andric 22170b57cec5SDimitry Andric StringRef RelSecName; 22188bcb0991SDimitry Andric if (auto NameOrErr = RelocatedSection->getName()) 22198bcb0991SDimitry Andric RelSecName = *NameOrErr; 22208bcb0991SDimitry Andric else 22218bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 22220b57cec5SDimitry Andric 22230b57cec5SDimitry Andric // If the section we're relocating was relocated already by the JIT, 22240b57cec5SDimitry Andric // then we used the relocated version above, so we do not need to process 22250b57cec5SDimitry Andric // relocations for it now. 22268bcb0991SDimitry Andric StringRef RelSecData; 22270b57cec5SDimitry Andric if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) 22280b57cec5SDimitry Andric continue; 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric // In Mach-o files, the relocations do not need to be applied if 22310b57cec5SDimitry Andric // there is no load offset to apply. The value read at the 22320b57cec5SDimitry Andric // relocation point already factors in the section address 22330b57cec5SDimitry Andric // (actually applying the relocations will produce wrong results 22340b57cec5SDimitry Andric // as the section address will be added twice). 22350b57cec5SDimitry Andric if (!L && isa<MachOObjectFile>(&Obj)) 22360b57cec5SDimitry Andric continue; 22370b57cec5SDimitry Andric 223806c3fb27SDimitry Andric if (!Section.relocations().empty() && Name.ends_with(".dwo") && 22395f757f3fSDimitry Andric RelSecName.starts_with(".debug")) { 224006c3fb27SDimitry Andric HandleWarning(createError("unexpected relocations for dwo section '" + 224106c3fb27SDimitry Andric RelSecName + "'")); 224206c3fb27SDimitry Andric } 22430b57cec5SDimitry Andric 22440b57cec5SDimitry Andric // TODO: Add support for relocations in other sections as needed. 22450b57cec5SDimitry Andric // Record relocations for the debug_info and debug_line sections. 224606c3fb27SDimitry Andric RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._")); 22470b57cec5SDimitry Andric DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName); 22480b57cec5SDimitry Andric RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; 22490b57cec5SDimitry Andric if (!Map) { 22500b57cec5SDimitry Andric // Find debug_info and debug_types relocs by section rather than name 22510b57cec5SDimitry Andric // as there are multiple, comdat grouped, of these sections. 22520b57cec5SDimitry Andric if (RelSecName == "debug_info") 22530b57cec5SDimitry Andric Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection]) 22540b57cec5SDimitry Andric .Relocs; 22550b57cec5SDimitry Andric else if (RelSecName == "debug_types") 22560b57cec5SDimitry Andric Map = 22570b57cec5SDimitry Andric &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection]) 22580b57cec5SDimitry Andric .Relocs; 22590b57cec5SDimitry Andric else 22600b57cec5SDimitry Andric continue; 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric if (Section.relocation_begin() == Section.relocation_end()) 22640b57cec5SDimitry Andric continue; 22650b57cec5SDimitry Andric 22660b57cec5SDimitry Andric // Symbol to [address, section index] cache mapping. 22670b57cec5SDimitry Andric std::map<SymbolRef, SymInfo> AddrCache; 2268e8d8bef9SDimitry Andric SupportsRelocation Supports; 22690b57cec5SDimitry Andric RelocationResolver Resolver; 22700b57cec5SDimitry Andric std::tie(Supports, Resolver) = getRelocationResolver(Obj); 22710b57cec5SDimitry Andric for (const RelocationRef &Reloc : Section.relocations()) { 22720b57cec5SDimitry Andric // FIXME: it's not clear how to correctly handle scattered 22730b57cec5SDimitry Andric // relocations. 22740b57cec5SDimitry Andric if (isRelocScattered(Obj, Reloc)) 22750b57cec5SDimitry Andric continue; 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric Expected<SymInfo> SymInfoOrErr = 22780b57cec5SDimitry Andric getSymbolInfo(Obj, Reloc, L, AddrCache); 22790b57cec5SDimitry Andric if (!SymInfoOrErr) { 22805ffd83dbSDimitry Andric HandleError(SymInfoOrErr.takeError()); 22810b57cec5SDimitry Andric continue; 22820b57cec5SDimitry Andric } 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric // Check if Resolver can handle this relocation type early so as not to 22850b57cec5SDimitry Andric // handle invalid cases in DWARFDataExtractor. 22860b57cec5SDimitry Andric // 22870b57cec5SDimitry Andric // TODO Don't store Resolver in every RelocAddrEntry. 22880b57cec5SDimitry Andric if (Supports && Supports(Reloc.getType())) { 22890b57cec5SDimitry Andric auto I = Map->try_emplace( 22900b57cec5SDimitry Andric Reloc.getOffset(), 2291bdd1243dSDimitry Andric RelocAddrEntry{ 2292bdd1243dSDimitry Andric SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address, 2293bdd1243dSDimitry Andric std::optional<object::RelocationRef>(), 0, Resolver}); 22940b57cec5SDimitry Andric // If we didn't successfully insert that's because we already had a 22950b57cec5SDimitry Andric // relocation for that offset. Store it as a second relocation in the 22960b57cec5SDimitry Andric // same RelocAddrEntry instead. 22970b57cec5SDimitry Andric if (!I.second) { 22980b57cec5SDimitry Andric RelocAddrEntry &entry = I.first->getSecond(); 22990b57cec5SDimitry Andric if (entry.Reloc2) { 23005ffd83dbSDimitry Andric HandleError(createError( 23010b57cec5SDimitry Andric "At most two relocations per offset are supported")); 23020b57cec5SDimitry Andric } 23030b57cec5SDimitry Andric entry.Reloc2 = Reloc; 23040b57cec5SDimitry Andric entry.SymbolValue2 = SymInfoOrErr->Address; 23050b57cec5SDimitry Andric } 23060b57cec5SDimitry Andric } else { 23070b57cec5SDimitry Andric SmallString<32> Type; 23080b57cec5SDimitry Andric Reloc.getTypeName(Type); 23095ffd83dbSDimitry Andric // FIXME: Support more relocations & change this to an error 23105ffd83dbSDimitry Andric HandleWarning( 23110b57cec5SDimitry Andric createError("failed to compute relocation: " + Type + ", ", 23120b57cec5SDimitry Andric errorCodeToError(object_error::parse_failed))); 23130b57cec5SDimitry Andric } 23140b57cec5SDimitry Andric } 23150b57cec5SDimitry Andric } 23160b57cec5SDimitry Andric 23170b57cec5SDimitry Andric for (SectionName &S : SectionNames) 23180b57cec5SDimitry Andric if (SectionAmountMap[S.Name] > 1) 23190b57cec5SDimitry Andric S.IsNameUnique = false; 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 2322bdd1243dSDimitry Andric std::optional<RelocAddrEntry> find(const DWARFSection &S, 23230b57cec5SDimitry Andric uint64_t Pos) const override { 23240b57cec5SDimitry Andric auto &Sec = static_cast<const DWARFSectionMap &>(S); 23250b57cec5SDimitry Andric RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos); 23260b57cec5SDimitry Andric if (AI == Sec.Relocs.end()) 2327bdd1243dSDimitry Andric return std::nullopt; 23280b57cec5SDimitry Andric return AI->second; 23290b57cec5SDimitry Andric } 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric const object::ObjectFile *getFile() const override { return Obj; } 23320b57cec5SDimitry Andric 23330b57cec5SDimitry Andric ArrayRef<SectionName> getSectionNames() const override { 23340b57cec5SDimitry Andric return SectionNames; 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric bool isLittleEndian() const override { return IsLittleEndian; } 23380b57cec5SDimitry Andric StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; } 23390b57cec5SDimitry Andric const DWARFSection &getLineDWOSection() const override { 23400b57cec5SDimitry Andric return LineDWOSection; 23410b57cec5SDimitry Andric } 23420b57cec5SDimitry Andric const DWARFSection &getLocDWOSection() const override { 23430b57cec5SDimitry Andric return LocDWOSection; 23440b57cec5SDimitry Andric } 23458bcb0991SDimitry Andric StringRef getStrDWOSection() const override { return StrDWOSection; } 23468bcb0991SDimitry Andric const DWARFSection &getStrOffsetsDWOSection() const override { 23478bcb0991SDimitry Andric return StrOffsetsDWOSection; 23480b57cec5SDimitry Andric } 23498bcb0991SDimitry Andric const DWARFSection &getRangesDWOSection() const override { 23508bcb0991SDimitry Andric return RangesDWOSection; 23510b57cec5SDimitry Andric } 23520b57cec5SDimitry Andric const DWARFSection &getRnglistsDWOSection() const override { 23530b57cec5SDimitry Andric return RnglistsDWOSection; 23540b57cec5SDimitry Andric } 2355480093f4SDimitry Andric const DWARFSection &getLoclistsDWOSection() const override { 2356480093f4SDimitry Andric return LoclistsDWOSection; 2357480093f4SDimitry Andric } 23580b57cec5SDimitry Andric const DWARFSection &getAddrSection() const override { return AddrSection; } 23590b57cec5SDimitry Andric StringRef getCUIndexSection() const override { return CUIndexSection; } 23600b57cec5SDimitry Andric StringRef getGdbIndexSection() const override { return GdbIndexSection; } 23610b57cec5SDimitry Andric StringRef getTUIndexSection() const override { return TUIndexSection; } 23620b57cec5SDimitry Andric 23630b57cec5SDimitry Andric // DWARF v5 23648bcb0991SDimitry Andric const DWARFSection &getStrOffsetsSection() const override { 23658bcb0991SDimitry Andric return StrOffsetsSection; 23660b57cec5SDimitry Andric } 23678bcb0991SDimitry Andric StringRef getLineStrSection() const override { return LineStrSection; } 23680b57cec5SDimitry Andric 23690b57cec5SDimitry Andric // Sections for DWARF5 split dwarf proposal. 23700b57cec5SDimitry Andric void forEachInfoDWOSections( 23710b57cec5SDimitry Andric function_ref<void(const DWARFSection &)> F) const override { 23720b57cec5SDimitry Andric for (auto &P : InfoDWOSections) 23730b57cec5SDimitry Andric F(P.second); 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric void forEachTypesDWOSections( 23760b57cec5SDimitry Andric function_ref<void(const DWARFSection &)> F) const override { 23770b57cec5SDimitry Andric for (auto &P : TypesDWOSections) 23780b57cec5SDimitry Andric F(P.second); 23790b57cec5SDimitry Andric } 23800b57cec5SDimitry Andric 23810b57cec5SDimitry Andric StringRef getAbbrevSection() const override { return AbbrevSection; } 23820b57cec5SDimitry Andric const DWARFSection &getLocSection() const override { return LocSection; } 23838bcb0991SDimitry Andric const DWARFSection &getLoclistsSection() const override { return LoclistsSection; } 23848bcb0991SDimitry Andric StringRef getArangesSection() const override { return ArangesSection; } 23858bcb0991SDimitry Andric const DWARFSection &getFrameSection() const override { 23868bcb0991SDimitry Andric return FrameSection; 23870b57cec5SDimitry Andric } 23880b57cec5SDimitry Andric const DWARFSection &getEHFrameSection() const override { 23890b57cec5SDimitry Andric return EHFrameSection; 23900b57cec5SDimitry Andric } 23910b57cec5SDimitry Andric const DWARFSection &getLineSection() const override { return LineSection; } 23928bcb0991SDimitry Andric StringRef getStrSection() const override { return StrSection; } 23938bcb0991SDimitry Andric const DWARFSection &getRangesSection() const override { return RangesSection; } 23940b57cec5SDimitry Andric const DWARFSection &getRnglistsSection() const override { 23950b57cec5SDimitry Andric return RnglistsSection; 23960b57cec5SDimitry Andric } 23975ffd83dbSDimitry Andric const DWARFSection &getMacroSection() const override { return MacroSection; } 23985ffd83dbSDimitry Andric StringRef getMacroDWOSection() const override { return MacroDWOSection; } 23990b57cec5SDimitry Andric StringRef getMacinfoSection() const override { return MacinfoSection; } 2400480093f4SDimitry Andric StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; } 24018bcb0991SDimitry Andric const DWARFSection &getPubnamesSection() const override { return PubnamesSection; } 24028bcb0991SDimitry Andric const DWARFSection &getPubtypesSection() const override { return PubtypesSection; } 24038bcb0991SDimitry Andric const DWARFSection &getGnuPubnamesSection() const override { 24048bcb0991SDimitry Andric return GnuPubnamesSection; 24050b57cec5SDimitry Andric } 24068bcb0991SDimitry Andric const DWARFSection &getGnuPubtypesSection() const override { 24078bcb0991SDimitry Andric return GnuPubtypesSection; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric const DWARFSection &getAppleNamesSection() const override { 24100b57cec5SDimitry Andric return AppleNamesSection; 24110b57cec5SDimitry Andric } 24120b57cec5SDimitry Andric const DWARFSection &getAppleTypesSection() const override { 24130b57cec5SDimitry Andric return AppleTypesSection; 24140b57cec5SDimitry Andric } 24150b57cec5SDimitry Andric const DWARFSection &getAppleNamespacesSection() const override { 24160b57cec5SDimitry Andric return AppleNamespacesSection; 24170b57cec5SDimitry Andric } 24180b57cec5SDimitry Andric const DWARFSection &getAppleObjCSection() const override { 24190b57cec5SDimitry Andric return AppleObjCSection; 24200b57cec5SDimitry Andric } 24218bcb0991SDimitry Andric const DWARFSection &getNamesSection() const override { 24228bcb0991SDimitry Andric return NamesSection; 24230b57cec5SDimitry Andric } 24240b57cec5SDimitry Andric 24250b57cec5SDimitry Andric StringRef getFileName() const override { return FileName; } 24260b57cec5SDimitry Andric uint8_t getAddressSize() const override { return AddressSize; } 24270b57cec5SDimitry Andric void forEachInfoSections( 24280b57cec5SDimitry Andric function_ref<void(const DWARFSection &)> F) const override { 24290b57cec5SDimitry Andric for (auto &P : InfoSections) 24300b57cec5SDimitry Andric F(P.second); 24310b57cec5SDimitry Andric } 24320b57cec5SDimitry Andric void forEachTypesSections( 24330b57cec5SDimitry Andric function_ref<void(const DWARFSection &)> F) const override { 24340b57cec5SDimitry Andric for (auto &P : TypesSections) 24350b57cec5SDimitry Andric F(P.second); 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric }; 24380b57cec5SDimitry Andric } // namespace 24390b57cec5SDimitry Andric 24400b57cec5SDimitry Andric std::unique_ptr<DWARFContext> 2441349cc55cSDimitry Andric DWARFContext::create(const object::ObjectFile &Obj, 2442349cc55cSDimitry Andric ProcessDebugRelocations RelocAction, 2443349cc55cSDimitry Andric const LoadedObjectInfo *L, std::string DWPName, 24445ffd83dbSDimitry Andric std::function<void(Error)> RecoverableErrorHandler, 24455f757f3fSDimitry Andric std::function<void(Error)> WarningHandler, 24465f757f3fSDimitry Andric bool ThreadSafe) { 2447349cc55cSDimitry Andric auto DObj = std::make_unique<DWARFObjInMemory>( 2448349cc55cSDimitry Andric Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction); 24495f757f3fSDimitry Andric return std::make_unique<DWARFContext>(std::move(DObj), 24505f757f3fSDimitry Andric std::move(DWPName), 24515ffd83dbSDimitry Andric RecoverableErrorHandler, 24525f757f3fSDimitry Andric WarningHandler, 24535f757f3fSDimitry Andric ThreadSafe); 24540b57cec5SDimitry Andric } 24550b57cec5SDimitry Andric 24560b57cec5SDimitry Andric std::unique_ptr<DWARFContext> 24570b57cec5SDimitry Andric DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, 24585ffd83dbSDimitry Andric uint8_t AddrSize, bool isLittleEndian, 24595ffd83dbSDimitry Andric std::function<void(Error)> RecoverableErrorHandler, 24605f757f3fSDimitry Andric std::function<void(Error)> WarningHandler, 24615f757f3fSDimitry Andric bool ThreadSafe) { 24620b57cec5SDimitry Andric auto DObj = 24638bcb0991SDimitry Andric std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian); 24645ffd83dbSDimitry Andric return std::make_unique<DWARFContext>( 24655f757f3fSDimitry Andric std::move(DObj), "", RecoverableErrorHandler, WarningHandler, ThreadSafe); 24660b57cec5SDimitry Andric } 24670b57cec5SDimitry Andric 24680b57cec5SDimitry Andric uint8_t DWARFContext::getCUAddrSize() { 24690b57cec5SDimitry Andric // In theory, different compile units may have different address byte 24700b57cec5SDimitry Andric // sizes, but for simplicity we just use the address byte size of the 24715ffd83dbSDimitry Andric // first compile unit. In practice the address size field is repeated across 24720b57cec5SDimitry Andric // various DWARF headers (at least in version 5) to make it easier to dump 24730b57cec5SDimitry Andric // them independently, not to enable varying the address size. 2474e8d8bef9SDimitry Andric auto CUs = compile_units(); 24755ffd83dbSDimitry Andric return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize(); 24760b57cec5SDimitry Andric } 2477