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
fixupIndexV4(DWARFContext & C,DWARFUnitIndex & Index)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
fixupIndexV5(DWARFContext & C,DWARFUnitIndex & Index)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
fixupIndex(DWARFContext & C,DWARFUnitIndex & Index)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>
getAccelTable(std::unique_ptr<T> & Cache,const DWARFObject & Obj,const DWARFSection & Section,StringRef StringSection,bool IsLittleEndian)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>
parseMacroOrMacinfo(MacroSecType SectionType)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:
ThreadUnsafeDWARFContextState(DWARFContext & DC,std::string & DWP)2865f757f3fSDimitry Andric ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :
2875f757f3fSDimitry Andric DWARFContext::DWARFContextState(DC),
2885f757f3fSDimitry Andric DWPName(std::move(DWP)) {}
2895f757f3fSDimitry Andric
getNormalUnits()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
getDWOUnits(bool Lazy)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
getDebugAbbrevDWO()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
getCUIndex()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 }
getTUIndex()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
getGdbIndex()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
getDebugAbbrev()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
getDebugLoc()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
getDebugAranges()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 *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)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
clearLineTableForUnit(DWARFUnit * U)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
getDebugFrame()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
getEHFrame()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
getDebugMacinfo()4885f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfo() override {
4895f757f3fSDimitry Andric if (!Macinfo)
4905f757f3fSDimitry Andric Macinfo = parseMacroOrMacinfo(MacinfoSection);
4915f757f3fSDimitry Andric return Macinfo.get();
4925f757f3fSDimitry Andric }
getDebugMacinfoDWO()4935f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfoDWO() override {
4945f757f3fSDimitry Andric if (!MacinfoDWO)
4955f757f3fSDimitry Andric MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);
4965f757f3fSDimitry Andric return MacinfoDWO.get();
4975f757f3fSDimitry Andric }
getDebugMacro()4985f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacro() override {
4995f757f3fSDimitry Andric if (!Macro)
5005f757f3fSDimitry Andric Macro = parseMacroOrMacinfo(MacroSection);
5015f757f3fSDimitry Andric return Macro.get();
5025f757f3fSDimitry Andric }
getDebugMacroDWO()5035f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacroDWO() override {
5045f757f3fSDimitry Andric if (!MacroDWO)
5055f757f3fSDimitry Andric MacroDWO = parseMacroOrMacinfo(MacroDwoSection);
5065f757f3fSDimitry Andric return MacroDWO.get();
5075f757f3fSDimitry Andric }
getDebugNames()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 }
getAppleNames()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 }
getAppleTypes()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 }
getAppleNamespaces()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 }
getAppleObjC()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>
getDWOContext(StringRef AbsolutePath)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
isThreadSafe() const5955f757f3fSDimitry Andric bool isThreadSafe() const override { return false; }
5965f757f3fSDimitry Andric
getNormalTypeUnitMap()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
getDWOTypeUnitMap()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 *> &
getTypeUnitMap(bool IsDWO)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:
ThreadSafeState(DWARFContext & DC,std::string & DWP)6345f757f3fSDimitry Andric ThreadSafeState(DWARFContext &DC, std::string &DWP) :
6355f757f3fSDimitry Andric ThreadUnsafeDWARFContextState(DC, DWP) {}
6365f757f3fSDimitry Andric
getNormalUnits()6375f757f3fSDimitry Andric DWARFUnitVector &getNormalUnits() override {
6385f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6395f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getNormalUnits();
6405f757f3fSDimitry Andric }
getDWOUnits(bool Lazy)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 }
getCUIndex()6485f757f3fSDimitry Andric const DWARFUnitIndex &getCUIndex() override {
6495f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6505f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getCUIndex();
6515f757f3fSDimitry Andric }
getDebugAbbrevDWO()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
getTUIndex()6575f757f3fSDimitry Andric const DWARFUnitIndex &getTUIndex() override {
6585f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6595f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getTUIndex();
6605f757f3fSDimitry Andric }
getGdbIndex()6615f757f3fSDimitry Andric DWARFGdbIndex &getGdbIndex() override {
6625f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6635f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getGdbIndex();
6645f757f3fSDimitry Andric }
getDebugAbbrev()6655f757f3fSDimitry Andric const DWARFDebugAbbrev *getDebugAbbrev() override {
6665f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6675f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugAbbrev();
6685f757f3fSDimitry Andric }
getDebugLoc()6695f757f3fSDimitry Andric const DWARFDebugLoc *getDebugLoc() override {
6705f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6715f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugLoc();
6725f757f3fSDimitry Andric }
getDebugAranges()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 *>
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)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 }
clearLineTableForUnit(DWARFUnit * U)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 }
getDebugFrame()6865f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getDebugFrame() override {
6875f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6885f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugFrame();
6895f757f3fSDimitry Andric }
getEHFrame()6905f757f3fSDimitry Andric Expected<const DWARFDebugFrame *> getEHFrame() override {
6915f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6925f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getEHFrame();
6935f757f3fSDimitry Andric }
getDebugMacinfo()6945f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfo() override {
6955f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
6965f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacinfo();
6975f757f3fSDimitry Andric }
getDebugMacinfoDWO()6985f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacinfoDWO() override {
6995f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7005f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO();
7015f757f3fSDimitry Andric }
getDebugMacro()7025f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacro() override {
7035f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7045f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacro();
7055f757f3fSDimitry Andric }
getDebugMacroDWO()7065f757f3fSDimitry Andric const DWARFDebugMacro *getDebugMacroDWO() override {
7075f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7085f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugMacroDWO();
7095f757f3fSDimitry Andric }
getDebugNames()7105f757f3fSDimitry Andric const DWARFDebugNames &getDebugNames() override {
7115f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7125f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getDebugNames();
7135f757f3fSDimitry Andric }
getAppleNames()7145f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNames() override {
7155f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7165f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleNames();
7175f757f3fSDimitry Andric }
getAppleTypes()7185f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleTypes() override {
7195f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7205f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleTypes();
7215f757f3fSDimitry Andric }
getAppleNamespaces()7225f757f3fSDimitry Andric const AppleAcceleratorTable &getAppleNamespaces() override {
7235f757f3fSDimitry Andric std::unique_lock<std::recursive_mutex> LockGuard(Mutex);
7245f757f3fSDimitry Andric return ThreadUnsafeDWARFContextState::getAppleNamespaces();
7255f757f3fSDimitry Andric }
getAppleObjC()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>
getDWOContext(StringRef AbsolutePath)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
isThreadSafe() const7365f757f3fSDimitry Andric bool isThreadSafe() const override { return true; }
7375f757f3fSDimitry Andric
7385f757f3fSDimitry Andric const DenseMap<uint64_t, DWARFTypeUnit *> &
getTypeUnitMap(bool IsDWO)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
DWARFContext(std::unique_ptr<const DWARFObject> DObj,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)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.
dumpUUID(raw_ostream & OS,const ObjectFile & Obj)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
collectContributionData(DWARFContext::unit_iterator_range Units)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).
dumpStringOffsetsSection(raw_ostream & OS,DIDumpOptions DumpOpts,StringRef SectionName,const DWARFObject & Obj,const DWARFSection & StringOffsetsSection,StringRef StringSection,DWARFContext::unit_iterator_range Units,bool LittleEndian)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.
dumpAddrSection(raw_ostream & OS,DWARFDataExtractor & AddrData,DIDumpOptions DumpOpts,uint16_t Version,uint8_t AddrSize)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).
dumpRnglistsSection(raw_ostream & OS,DWARFDataExtractor & rnglistData,llvm::function_ref<std::optional<object::SectionedAddress> (uint32_t)> LookupPooledAddress,DIDumpOptions DumpOpts)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
dumpLoclistsSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,const DWARFObject & Obj,std::optional<uint64_t> DumpOffset)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
dumpPubTableSection(raw_ostream & OS,DIDumpOptions DumpOpts,DWARFDataExtractor Data,bool GnuStyle)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
dump(raw_ostream & OS,DIDumpOptions DumpOpts,std::array<std::optional<uint64_t>,DIDT_ID_Count> DumpOffsets)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
getTypeUnitForHash(uint16_t Version,uint64_t Hash,bool IsDWO)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
getDWOCompileUnitForHash(uint64_t Hash)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
getDIEForOffset(uint64_t Offset)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
verify(raw_ostream & OS,DIDumpOptions DumpOpts)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
getCUIndex()14160b57cec5SDimitry Andric const DWARFUnitIndex &DWARFContext::getCUIndex() {
14175f757f3fSDimitry Andric return State->getCUIndex();
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric
getTUIndex()14200b57cec5SDimitry Andric const DWARFUnitIndex &DWARFContext::getTUIndex() {
14215f757f3fSDimitry Andric return State->getTUIndex();
14220b57cec5SDimitry Andric }
14230b57cec5SDimitry Andric
getGdbIndex()14240b57cec5SDimitry Andric DWARFGdbIndex &DWARFContext::getGdbIndex() {
14255f757f3fSDimitry Andric return State->getGdbIndex();
14260b57cec5SDimitry Andric }
14270b57cec5SDimitry Andric
getDebugAbbrev()14280b57cec5SDimitry Andric const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
14295f757f3fSDimitry Andric return State->getDebugAbbrev();
14300b57cec5SDimitry Andric }
14310b57cec5SDimitry Andric
getDebugAbbrevDWO()14320b57cec5SDimitry Andric const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
14335f757f3fSDimitry Andric return State->getDebugAbbrevDWO();
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric
getDebugLoc()14360b57cec5SDimitry Andric const DWARFDebugLoc *DWARFContext::getDebugLoc() {
14375f757f3fSDimitry Andric return State->getDebugLoc();
14380b57cec5SDimitry Andric }
14390b57cec5SDimitry Andric
getDebugAranges()14400b57cec5SDimitry Andric const DWARFDebugAranges *DWARFContext::getDebugAranges() {
14415f757f3fSDimitry Andric return State->getDebugAranges();
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric
getDebugFrame()14445ffd83dbSDimitry Andric Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {
14455f757f3fSDimitry Andric return State->getDebugFrame();
14460b57cec5SDimitry Andric }
14470b57cec5SDimitry Andric
getEHFrame()14485ffd83dbSDimitry Andric Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {
14495f757f3fSDimitry Andric return State->getEHFrame();
14500b57cec5SDimitry Andric }
14510b57cec5SDimitry Andric
getDebugMacro()14525ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacro() {
14535f757f3fSDimitry Andric return State->getDebugMacro();
14545ffd83dbSDimitry Andric }
1455480093f4SDimitry Andric
getDebugMacroDWO()14565ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
14575f757f3fSDimitry Andric return State->getDebugMacroDWO();
1458480093f4SDimitry Andric }
1459480093f4SDimitry Andric
getDebugMacinfo()14605ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {
14615f757f3fSDimitry Andric return State->getDebugMacinfo();
14625ffd83dbSDimitry Andric }
14630b57cec5SDimitry Andric
getDebugMacinfoDWO()14645ffd83dbSDimitry Andric const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {
14655f757f3fSDimitry Andric return State->getDebugMacinfoDWO();
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric
getDebugNames()14690b57cec5SDimitry Andric const DWARFDebugNames &DWARFContext::getDebugNames() {
14705f757f3fSDimitry Andric return State->getDebugNames();
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric
getAppleNames()14730b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleNames() {
14745f757f3fSDimitry Andric return State->getAppleNames();
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric
getAppleTypes()14770b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleTypes() {
14785f757f3fSDimitry Andric return State->getAppleTypes();
14790b57cec5SDimitry Andric }
14800b57cec5SDimitry Andric
getAppleNamespaces()14810b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {
14825f757f3fSDimitry Andric return State->getAppleNamespaces();
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric
getAppleObjC()14850b57cec5SDimitry Andric const AppleAcceleratorTable &DWARFContext::getAppleObjC() {
14865f757f3fSDimitry Andric return State->getAppleObjC();
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric
14890b57cec5SDimitry Andric const DWARFDebugLine::LineTable *
getLineTableForUnit(DWARFUnit * U)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
getLineTableForUnit(DWARFUnit * U,function_ref<void (Error)> RecoverableErrorHandler)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
clearLineTableForUnit(DWARFUnit * U)150581ad6265SDimitry Andric void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {
15065f757f3fSDimitry Andric return State->clearLineTableForUnit(U);
150781ad6265SDimitry Andric }
150881ad6265SDimitry Andric
getDWOUnits(bool Lazy)15095f757f3fSDimitry Andric DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {
15105f757f3fSDimitry Andric return State->getDWOUnits(Lazy);
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric
getCompileUnitForOffset(uint64_t Offset)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
getCompileUnitForCodeAddress(uint64_t Address)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
getCompileUnitForDataAddress(uint64_t Address)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
getDIEsForAddress(uint64_t Address,bool CheckDWO)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"
getFunctionNameAndStartLineForAddress(DWARFCompileUnit * CU,uint64_t Address,FunctionNameKind Kind,DILineInfoSpecifier::FileLineInfoKind FileNameKind,std::string & FunctionName,std::string & StartFile,uint32_t & StartLine,std::optional<uint64_t> & StartAddress)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>
getExpressionFrameOffset(ArrayRef<uint8_t> Expr,std::optional<unsigned> FrameBaseReg)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
addLocalsForDie(DWARFCompileUnit * CU,DWARFDie Subprogram,DWARFDie Die,std::vector<DILocal> & Result)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>
getLocalsForAddress(object::SectionedAddress Address)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
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)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
getLineInfoForDataAddress(object::SectionedAddress Address)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
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Spec)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
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Spec)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>
getDWOContext(StringRef AbsolutePath)18930b57cec5SDimitry Andric DWARFContext::getDWOContext(StringRef AbsolutePath) {
18945f757f3fSDimitry Andric return State->getDWOContext(AbsolutePath);
18950b57cec5SDimitry Andric }
18960b57cec5SDimitry Andric
createError(const Twine & Reason,llvm::Error E)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
getSymbolInfo(const object::ObjectFile & Obj,const RelocationRef & Reloc,const LoadedObjectInfo * L,std::map<SymbolRef,SymInfo> & Cache)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
isRelocScattered(const object::ObjectFile & Obj,const RelocationRef & Reloc)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
mapNameToDWARFSection(StringRef Name)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
mapSectionToMember(StringRef Name)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.
maybeDecompress(const object::SectionRef & Sec,StringRef Name,StringRef & Data)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:
DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool IsLittleEndian)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 }
DWARFObjInMemory(const object::ObjectFile & Obj,const LoadedObjectInfo * L,function_ref<void (Error)> HandleError,function_ref<void (Error)> HandleWarning,DWARFContext::ProcessDebugRelocations RelocAction)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
find(const DWARFSection & S,uint64_t Pos) const2322bdd1243dSDimitry 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
getFile() const23310b57cec5SDimitry Andric const object::ObjectFile *getFile() const override { return Obj; }
23320b57cec5SDimitry Andric
getSectionNames() const23330b57cec5SDimitry Andric ArrayRef<SectionName> getSectionNames() const override {
23340b57cec5SDimitry Andric return SectionNames;
23350b57cec5SDimitry Andric }
23360b57cec5SDimitry Andric
isLittleEndian() const23370b57cec5SDimitry Andric bool isLittleEndian() const override { return IsLittleEndian; }
getAbbrevDWOSection() const23380b57cec5SDimitry Andric StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }
getLineDWOSection() const23390b57cec5SDimitry Andric const DWARFSection &getLineDWOSection() const override {
23400b57cec5SDimitry Andric return LineDWOSection;
23410b57cec5SDimitry Andric }
getLocDWOSection() const23420b57cec5SDimitry Andric const DWARFSection &getLocDWOSection() const override {
23430b57cec5SDimitry Andric return LocDWOSection;
23440b57cec5SDimitry Andric }
getStrDWOSection() const23458bcb0991SDimitry Andric StringRef getStrDWOSection() const override { return StrDWOSection; }
getStrOffsetsDWOSection() const23468bcb0991SDimitry Andric const DWARFSection &getStrOffsetsDWOSection() const override {
23478bcb0991SDimitry Andric return StrOffsetsDWOSection;
23480b57cec5SDimitry Andric }
getRangesDWOSection() const23498bcb0991SDimitry Andric const DWARFSection &getRangesDWOSection() const override {
23508bcb0991SDimitry Andric return RangesDWOSection;
23510b57cec5SDimitry Andric }
getRnglistsDWOSection() const23520b57cec5SDimitry Andric const DWARFSection &getRnglistsDWOSection() const override {
23530b57cec5SDimitry Andric return RnglistsDWOSection;
23540b57cec5SDimitry Andric }
getLoclistsDWOSection() const2355480093f4SDimitry Andric const DWARFSection &getLoclistsDWOSection() const override {
2356480093f4SDimitry Andric return LoclistsDWOSection;
2357480093f4SDimitry Andric }
getAddrSection() const23580b57cec5SDimitry Andric const DWARFSection &getAddrSection() const override { return AddrSection; }
getCUIndexSection() const23590b57cec5SDimitry Andric StringRef getCUIndexSection() const override { return CUIndexSection; }
getGdbIndexSection() const23600b57cec5SDimitry Andric StringRef getGdbIndexSection() const override { return GdbIndexSection; }
getTUIndexSection() const23610b57cec5SDimitry Andric StringRef getTUIndexSection() const override { return TUIndexSection; }
23620b57cec5SDimitry Andric
23630b57cec5SDimitry Andric // DWARF v5
getStrOffsetsSection() const23648bcb0991SDimitry Andric const DWARFSection &getStrOffsetsSection() const override {
23658bcb0991SDimitry Andric return StrOffsetsSection;
23660b57cec5SDimitry Andric }
getLineStrSection() const23678bcb0991SDimitry Andric StringRef getLineStrSection() const override { return LineStrSection; }
23680b57cec5SDimitry Andric
23690b57cec5SDimitry Andric // Sections for DWARF5 split dwarf proposal.
forEachInfoDWOSections(function_ref<void (const DWARFSection &)> F) const23700b57cec5SDimitry 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 }
forEachTypesDWOSections(function_ref<void (const DWARFSection &)> F) const23750b57cec5SDimitry 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
getAbbrevSection() const23810b57cec5SDimitry Andric StringRef getAbbrevSection() const override { return AbbrevSection; }
getLocSection() const23820b57cec5SDimitry Andric const DWARFSection &getLocSection() const override { return LocSection; }
getLoclistsSection() const23838bcb0991SDimitry Andric const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }
getArangesSection() const23848bcb0991SDimitry Andric StringRef getArangesSection() const override { return ArangesSection; }
getFrameSection() const23858bcb0991SDimitry Andric const DWARFSection &getFrameSection() const override {
23868bcb0991SDimitry Andric return FrameSection;
23870b57cec5SDimitry Andric }
getEHFrameSection() const23880b57cec5SDimitry Andric const DWARFSection &getEHFrameSection() const override {
23890b57cec5SDimitry Andric return EHFrameSection;
23900b57cec5SDimitry Andric }
getLineSection() const23910b57cec5SDimitry Andric const DWARFSection &getLineSection() const override { return LineSection; }
getStrSection() const23928bcb0991SDimitry Andric StringRef getStrSection() const override { return StrSection; }
getRangesSection() const23938bcb0991SDimitry Andric const DWARFSection &getRangesSection() const override { return RangesSection; }
getRnglistsSection() const23940b57cec5SDimitry Andric const DWARFSection &getRnglistsSection() const override {
23950b57cec5SDimitry Andric return RnglistsSection;
23960b57cec5SDimitry Andric }
getMacroSection() const23975ffd83dbSDimitry Andric const DWARFSection &getMacroSection() const override { return MacroSection; }
getMacroDWOSection() const23985ffd83dbSDimitry Andric StringRef getMacroDWOSection() const override { return MacroDWOSection; }
getMacinfoSection() const23990b57cec5SDimitry Andric StringRef getMacinfoSection() const override { return MacinfoSection; }
getMacinfoDWOSection() const2400480093f4SDimitry Andric StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
getPubnamesSection() const24018bcb0991SDimitry Andric const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
getPubtypesSection() const24028bcb0991SDimitry Andric const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
getGnuPubnamesSection() const24038bcb0991SDimitry Andric const DWARFSection &getGnuPubnamesSection() const override {
24048bcb0991SDimitry Andric return GnuPubnamesSection;
24050b57cec5SDimitry Andric }
getGnuPubtypesSection() const24068bcb0991SDimitry Andric const DWARFSection &getGnuPubtypesSection() const override {
24078bcb0991SDimitry Andric return GnuPubtypesSection;
24080b57cec5SDimitry Andric }
getAppleNamesSection() const24090b57cec5SDimitry Andric const DWARFSection &getAppleNamesSection() const override {
24100b57cec5SDimitry Andric return AppleNamesSection;
24110b57cec5SDimitry Andric }
getAppleTypesSection() const24120b57cec5SDimitry Andric const DWARFSection &getAppleTypesSection() const override {
24130b57cec5SDimitry Andric return AppleTypesSection;
24140b57cec5SDimitry Andric }
getAppleNamespacesSection() const24150b57cec5SDimitry Andric const DWARFSection &getAppleNamespacesSection() const override {
24160b57cec5SDimitry Andric return AppleNamespacesSection;
24170b57cec5SDimitry Andric }
getAppleObjCSection() const24180b57cec5SDimitry Andric const DWARFSection &getAppleObjCSection() const override {
24190b57cec5SDimitry Andric return AppleObjCSection;
24200b57cec5SDimitry Andric }
getNamesSection() const24218bcb0991SDimitry Andric const DWARFSection &getNamesSection() const override {
24228bcb0991SDimitry Andric return NamesSection;
24230b57cec5SDimitry Andric }
24240b57cec5SDimitry Andric
getFileName() const24250b57cec5SDimitry Andric StringRef getFileName() const override { return FileName; }
getAddressSize() const24260b57cec5SDimitry Andric uint8_t getAddressSize() const override { return AddressSize; }
forEachInfoSections(function_ref<void (const DWARFSection &)> F) const24270b57cec5SDimitry 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 }
forEachTypesSections(function_ref<void (const DWARFSection &)> F) const24320b57cec5SDimitry 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>
create(const object::ObjectFile & Obj,ProcessDebugRelocations RelocAction,const LoadedObjectInfo * L,std::string DWPName,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)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>
create(const StringMap<std::unique_ptr<MemoryBuffer>> & Sections,uint8_t AddrSize,bool isLittleEndian,std::function<void (Error)> RecoverableErrorHandler,std::function<void (Error)> WarningHandler,bool ThreadSafe)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
getCUAddrSize()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