Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
35269 views
//===- DWARFContext.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFContext.h"9#include "llvm/ADT/MapVector.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/SmallString.h"12#include "llvm/ADT/SmallVector.h"13#include "llvm/ADT/StringRef.h"14#include "llvm/ADT/StringSwitch.h"15#include "llvm/BinaryFormat/Dwarf.h"16#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"17#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"18#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"19#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"20#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"21#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"22#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"23#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"24#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"25#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"26#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"27#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"28#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"29#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"30#include "llvm/DebugInfo/DWARF/DWARFDie.h"31#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"32#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"33#include "llvm/DebugInfo/DWARF/DWARFListTable.h"34#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"35#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"36#include "llvm/DebugInfo/DWARF/DWARFSection.h"37#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"38#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"39#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"40#include "llvm/MC/TargetRegistry.h"41#include "llvm/Object/Decompressor.h"42#include "llvm/Object/MachO.h"43#include "llvm/Object/ObjectFile.h"44#include "llvm/Object/RelocationResolver.h"45#include "llvm/Support/Casting.h"46#include "llvm/Support/DataExtractor.h"47#include "llvm/Support/Error.h"48#include "llvm/Support/Format.h"49#include "llvm/Support/LEB128.h"50#include "llvm/Support/FormatVariadic.h"51#include "llvm/Support/MemoryBuffer.h"52#include "llvm/Support/Path.h"53#include "llvm/Support/raw_ostream.h"54#include <algorithm>55#include <cstdint>56#include <deque>57#include <map>58#include <string>59#include <utility>60#include <vector>6162using namespace llvm;63using namespace dwarf;64using namespace object;6566#define DEBUG_TYPE "dwarf"6768using DWARFLineTable = DWARFDebugLine::LineTable;69using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;70using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;717273void fixupIndexV4(DWARFContext &C, DWARFUnitIndex &Index) {74using EntryType = DWARFUnitIndex::Entry::SectionContribution;75using EntryMap = DenseMap<uint32_t, EntryType>;76EntryMap Map;77const auto &DObj = C.getDWARFObj();78if (DObj.getCUIndexSection().empty())79return;8081uint64_t Offset = 0;82uint32_t TruncOffset = 0;83DObj.forEachInfoDWOSections([&](const DWARFSection &S) {84if (!(C.getParseCUTUIndexManually() ||85S.Data.size() >= std::numeric_limits<uint32_t>::max()))86return;8788DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);89while (Data.isValidOffset(Offset)) {90DWARFUnitHeader Header;91if (Error ExtractionErr = Header.extract(92C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {93C.getWarningHandler()(94createError("Failed to parse CU header in DWP file: " +95toString(std::move(ExtractionErr))));96Map.clear();97break;98}99100auto Iter = Map.insert({TruncOffset,101{Header.getOffset(), Header.getNextUnitOffset() -102Header.getOffset()}});103if (!Iter.second) {104logAllUnhandledErrors(105createError("Collision occured between for truncated offset 0x" +106Twine::utohexstr(TruncOffset)),107errs());108Map.clear();109return;110}111112Offset = Header.getNextUnitOffset();113TruncOffset = Offset;114}115});116117if (Map.empty())118return;119120for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {121if (!E.isValid())122continue;123DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();124auto Iter = Map.find(CUOff.getOffset());125if (Iter == Map.end()) {126logAllUnhandledErrors(createError("Could not find CU offset 0x" +127Twine::utohexstr(CUOff.getOffset()) +128" in the Map"),129errs());130break;131}132CUOff.setOffset(Iter->second.getOffset());133if (CUOff.getOffset() != Iter->second.getOffset())134logAllUnhandledErrors(createError("Length of CU in CU index doesn't "135"match calculated length at offset 0x" +136Twine::utohexstr(CUOff.getOffset())),137errs());138}139}140141void fixupIndexV5(DWARFContext &C, DWARFUnitIndex &Index) {142DenseMap<uint64_t, uint64_t> Map;143144const auto &DObj = C.getDWARFObj();145DObj.forEachInfoDWOSections([&](const DWARFSection &S) {146if (!(C.getParseCUTUIndexManually() ||147S.Data.size() >= std::numeric_limits<uint32_t>::max()))148return;149DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);150uint64_t Offset = 0;151while (Data.isValidOffset(Offset)) {152DWARFUnitHeader Header;153if (Error ExtractionErr = Header.extract(154C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {155C.getWarningHandler()(156createError("Failed to parse CU header in DWP file: " +157toString(std::move(ExtractionErr))));158break;159}160bool CU = Header.getUnitType() == DW_UT_split_compile;161uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash();162Map[Sig] = Header.getOffset();163Offset = Header.getNextUnitOffset();164}165});166if (Map.empty())167return;168for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {169if (!E.isValid())170continue;171DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();172auto Iter = Map.find(E.getSignature());173if (Iter == Map.end()) {174logAllUnhandledErrors(175createError("Could not find unit with signature 0x" +176Twine::utohexstr(E.getSignature()) + " in the Map"),177errs());178break;179}180CUOff.setOffset(Iter->second);181}182}183184void fixupIndex(DWARFContext &C, DWARFUnitIndex &Index) {185if (Index.getVersion() < 5)186fixupIndexV4(C, Index);187else188fixupIndexV5(C, Index);189}190191template <typename T>192static T &getAccelTable(std::unique_ptr<T> &Cache, const DWARFObject &Obj,193const DWARFSection &Section, StringRef StringSection,194bool IsLittleEndian) {195if (Cache)196return *Cache;197DWARFDataExtractor AccelSection(Obj, Section, IsLittleEndian, 0);198DataExtractor StrData(StringSection, IsLittleEndian, 0);199Cache = std::make_unique<T>(AccelSection, StrData);200if (Error E = Cache->extract())201llvm::consumeError(std::move(E));202return *Cache;203}204205206std::unique_ptr<DWARFDebugMacro>207DWARFContext::DWARFContextState::parseMacroOrMacinfo(MacroSecType SectionType) {208auto Macro = std::make_unique<DWARFDebugMacro>();209auto ParseAndDump = [&](DWARFDataExtractor &Data, bool IsMacro) {210if (Error Err = IsMacro ? Macro->parseMacro(SectionType == MacroSection211? D.compile_units()212: D.dwo_compile_units(),213SectionType == MacroSection214? D.getStringExtractor()215: D.getStringDWOExtractor(),216Data)217: Macro->parseMacinfo(Data)) {218D.getRecoverableErrorHandler()(std::move(Err));219Macro = nullptr;220}221};222const DWARFObject &DObj = D.getDWARFObj();223switch (SectionType) {224case MacinfoSection: {225DWARFDataExtractor Data(DObj.getMacinfoSection(), D.isLittleEndian(), 0);226ParseAndDump(Data, /*IsMacro=*/false);227break;228}229case MacinfoDwoSection: {230DWARFDataExtractor Data(DObj.getMacinfoDWOSection(), D.isLittleEndian(), 0);231ParseAndDump(Data, /*IsMacro=*/false);232break;233}234case MacroSection: {235DWARFDataExtractor Data(DObj, DObj.getMacroSection(), D.isLittleEndian(),2360);237ParseAndDump(Data, /*IsMacro=*/true);238break;239}240case MacroDwoSection: {241DWARFDataExtractor Data(DObj.getMacroDWOSection(), D.isLittleEndian(), 0);242ParseAndDump(Data, /*IsMacro=*/true);243break;244}245}246return Macro;247}248249namespace {250class ThreadUnsafeDWARFContextState : public DWARFContext::DWARFContextState {251252DWARFUnitVector NormalUnits;253std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits;254std::unique_ptr<DWARFUnitIndex> CUIndex;255std::unique_ptr<DWARFGdbIndex> GdbIndex;256std::unique_ptr<DWARFUnitIndex> TUIndex;257std::unique_ptr<DWARFDebugAbbrev> Abbrev;258std::unique_ptr<DWARFDebugLoc> Loc;259std::unique_ptr<DWARFDebugAranges> Aranges;260std::unique_ptr<DWARFDebugLine> Line;261std::unique_ptr<DWARFDebugFrame> DebugFrame;262std::unique_ptr<DWARFDebugFrame> EHFrame;263std::unique_ptr<DWARFDebugMacro> Macro;264std::unique_ptr<DWARFDebugMacro> Macinfo;265std::unique_ptr<DWARFDebugNames> Names;266std::unique_ptr<AppleAcceleratorTable> AppleNames;267std::unique_ptr<AppleAcceleratorTable> AppleTypes;268std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;269std::unique_ptr<AppleAcceleratorTable> AppleObjC;270DWARFUnitVector DWOUnits;271std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits;272std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;273std::unique_ptr<DWARFDebugMacro> MacinfoDWO;274std::unique_ptr<DWARFDebugMacro> MacroDWO;275struct DWOFile {276object::OwningBinary<object::ObjectFile> File;277std::unique_ptr<DWARFContext> Context;278};279StringMap<std::weak_ptr<DWOFile>> DWOFiles;280std::weak_ptr<DWOFile> DWP;281bool CheckedForDWP = false;282std::string DWPName;283284public:285ThreadUnsafeDWARFContextState(DWARFContext &DC, std::string &DWP) :286DWARFContext::DWARFContextState(DC),287DWPName(std::move(DWP)) {}288289DWARFUnitVector &getNormalUnits() override {290if (NormalUnits.empty()) {291const DWARFObject &DObj = D.getDWARFObj();292DObj.forEachInfoSections([&](const DWARFSection &S) {293NormalUnits.addUnitsForSection(D, S, DW_SECT_INFO);294});295NormalUnits.finishedInfoUnits();296DObj.forEachTypesSections([&](const DWARFSection &S) {297NormalUnits.addUnitsForSection(D, S, DW_SECT_EXT_TYPES);298});299}300return NormalUnits;301}302303DWARFUnitVector &getDWOUnits(bool Lazy) override {304if (DWOUnits.empty()) {305const DWARFObject &DObj = D.getDWARFObj();306307DObj.forEachInfoDWOSections([&](const DWARFSection &S) {308DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_INFO, Lazy);309});310DWOUnits.finishedInfoUnits();311DObj.forEachTypesDWOSections([&](const DWARFSection &S) {312DWOUnits.addUnitsForDWOSection(D, S, DW_SECT_EXT_TYPES, Lazy);313});314}315return DWOUnits;316}317318const DWARFDebugAbbrev *getDebugAbbrevDWO() override {319if (AbbrevDWO)320return AbbrevDWO.get();321const DWARFObject &DObj = D.getDWARFObj();322DataExtractor abbrData(DObj.getAbbrevDWOSection(), D.isLittleEndian(), 0);323AbbrevDWO = std::make_unique<DWARFDebugAbbrev>(abbrData);324return AbbrevDWO.get();325}326327const DWARFUnitIndex &getCUIndex() override {328if (CUIndex)329return *CUIndex;330331DataExtractor Data(D.getDWARFObj().getCUIndexSection(),332D.isLittleEndian(), 0);333CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);334if (CUIndex->parse(Data))335fixupIndex(D, *CUIndex);336return *CUIndex;337}338const DWARFUnitIndex &getTUIndex() override {339if (TUIndex)340return *TUIndex;341342DataExtractor Data(D.getDWARFObj().getTUIndexSection(),343D.isLittleEndian(), 0);344TUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_EXT_TYPES);345bool isParseSuccessful = TUIndex->parse(Data);346// If we are parsing TU-index and for .debug_types section we don't need347// to do anything.348if (isParseSuccessful && TUIndex->getVersion() != 2)349fixupIndex(D, *TUIndex);350return *TUIndex;351}352353DWARFGdbIndex &getGdbIndex() override {354if (GdbIndex)355return *GdbIndex;356357DataExtractor Data(D.getDWARFObj().getGdbIndexSection(), true /*LE*/, 0);358GdbIndex = std::make_unique<DWARFGdbIndex>();359GdbIndex->parse(Data);360return *GdbIndex;361}362363const DWARFDebugAbbrev *getDebugAbbrev() override {364if (Abbrev)365return Abbrev.get();366367DataExtractor Data(D.getDWARFObj().getAbbrevSection(),368D.isLittleEndian(), 0);369Abbrev = std::make_unique<DWARFDebugAbbrev>(Data);370return Abbrev.get();371}372373const DWARFDebugLoc *getDebugLoc() override {374if (Loc)375return Loc.get();376377const DWARFObject &DObj = D.getDWARFObj();378// Assume all units have the same address byte size.379auto Data =380D.getNumCompileUnits()381? DWARFDataExtractor(DObj, DObj.getLocSection(), D.isLittleEndian(),382D.getUnitAtIndex(0)->getAddressByteSize())383: DWARFDataExtractor("", D.isLittleEndian(), 0);384Loc = std::make_unique<DWARFDebugLoc>(std::move(Data));385return Loc.get();386}387388const DWARFDebugAranges *getDebugAranges() override {389if (Aranges)390return Aranges.get();391392Aranges = std::make_unique<DWARFDebugAranges>();393Aranges->generate(&D);394return Aranges.get();395}396397Expected<const DWARFDebugLine::LineTable *>398getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {399if (!Line)400Line = std::make_unique<DWARFDebugLine>();401402auto UnitDIE = U->getUnitDIE();403if (!UnitDIE)404return nullptr;405406auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));407if (!Offset)408return nullptr; // No line table for this compile unit.409410uint64_t stmtOffset = *Offset + U->getLineTableOffset();411// See if the line table is cached.412if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))413return lt;414415// Make sure the offset is good before we try to parse.416if (stmtOffset >= U->getLineSection().Data.size())417return nullptr;418419// We have to parse it first.420DWARFDataExtractor Data(U->getContext().getDWARFObj(), U->getLineSection(),421U->isLittleEndian(), U->getAddressByteSize());422return Line->getOrParseLineTable(Data, stmtOffset, U->getContext(), U,423RecoverableErrorHandler);424425}426427void clearLineTableForUnit(DWARFUnit *U) override {428if (!Line)429return;430431auto UnitDIE = U->getUnitDIE();432if (!UnitDIE)433return;434435auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));436if (!Offset)437return;438439uint64_t stmtOffset = *Offset + U->getLineTableOffset();440Line->clearLineTable(stmtOffset);441}442443Expected<const DWARFDebugFrame *> getDebugFrame() override {444if (DebugFrame)445return DebugFrame.get();446const DWARFObject &DObj = D.getDWARFObj();447const DWARFSection &DS = DObj.getFrameSection();448449// There's a "bug" in the DWARFv3 standard with respect to the target address450// size within debug frame sections. While DWARF is supposed to be independent451// of its container, FDEs have fields with size being "target address size",452// which isn't specified in DWARF in general. It's only specified for CUs, but453// .eh_frame can appear without a .debug_info section. Follow the example of454// other tools (libdwarf) and extract this from the container (ObjectFile455// provides this information). This problem is fixed in DWARFv4456// See this dwarf-discuss discussion for more details:457// http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html458DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),459DObj.getAddressSize());460auto DF =461std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/false,462DS.Address);463if (Error E = DF->parse(Data))464return std::move(E);465466DebugFrame.swap(DF);467return DebugFrame.get();468}469470Expected<const DWARFDebugFrame *> getEHFrame() override {471if (EHFrame)472return EHFrame.get();473const DWARFObject &DObj = D.getDWARFObj();474475const DWARFSection &DS = DObj.getEHFrameSection();476DWARFDataExtractor Data(DObj, DS, D.isLittleEndian(),477DObj.getAddressSize());478auto DF =479std::make_unique<DWARFDebugFrame>(D.getArch(), /*IsEH=*/true,480DS.Address);481if (Error E = DF->parse(Data))482return std::move(E);483EHFrame.swap(DF);484return EHFrame.get();485}486487const DWARFDebugMacro *getDebugMacinfo() override {488if (!Macinfo)489Macinfo = parseMacroOrMacinfo(MacinfoSection);490return Macinfo.get();491}492const DWARFDebugMacro *getDebugMacinfoDWO() override {493if (!MacinfoDWO)494MacinfoDWO = parseMacroOrMacinfo(MacinfoDwoSection);495return MacinfoDWO.get();496}497const DWARFDebugMacro *getDebugMacro() override {498if (!Macro)499Macro = parseMacroOrMacinfo(MacroSection);500return Macro.get();501}502const DWARFDebugMacro *getDebugMacroDWO() override {503if (!MacroDWO)504MacroDWO = parseMacroOrMacinfo(MacroDwoSection);505return MacroDWO.get();506}507const DWARFDebugNames &getDebugNames() override {508const DWARFObject &DObj = D.getDWARFObj();509return getAccelTable(Names, DObj, DObj.getNamesSection(),510DObj.getStrSection(), D.isLittleEndian());511}512const AppleAcceleratorTable &getAppleNames() override {513const DWARFObject &DObj = D.getDWARFObj();514return getAccelTable(AppleNames, DObj, DObj.getAppleNamesSection(),515DObj.getStrSection(), D.isLittleEndian());516517}518const AppleAcceleratorTable &getAppleTypes() override {519const DWARFObject &DObj = D.getDWARFObj();520return getAccelTable(AppleTypes, DObj, DObj.getAppleTypesSection(),521DObj.getStrSection(), D.isLittleEndian());522523}524const AppleAcceleratorTable &getAppleNamespaces() override {525const DWARFObject &DObj = D.getDWARFObj();526return getAccelTable(AppleNamespaces, DObj,527DObj.getAppleNamespacesSection(),528DObj.getStrSection(), D.isLittleEndian());529530}531const AppleAcceleratorTable &getAppleObjC() override {532const DWARFObject &DObj = D.getDWARFObj();533return getAccelTable(AppleObjC, DObj, DObj.getAppleObjCSection(),534DObj.getStrSection(), D.isLittleEndian());535}536537std::shared_ptr<DWARFContext>538getDWOContext(StringRef AbsolutePath) override {539if (auto S = DWP.lock()) {540DWARFContext *Ctxt = S->Context.get();541return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);542}543544std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];545546if (auto S = Entry->lock()) {547DWARFContext *Ctxt = S->Context.get();548return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);549}550551const DWARFObject &DObj = D.getDWARFObj();552553Expected<OwningBinary<ObjectFile>> Obj = [&] {554if (!CheckedForDWP) {555SmallString<128> DWPName;556auto Obj = object::ObjectFile::createObjectFile(557this->DWPName.empty()558? (DObj.getFileName() + ".dwp").toStringRef(DWPName)559: StringRef(this->DWPName));560if (Obj) {561Entry = &DWP;562return Obj;563} else {564CheckedForDWP = true;565// TODO: Should this error be handled (maybe in a high verbosity mode)566// before falling back to .dwo files?567consumeError(Obj.takeError());568}569}570571return object::ObjectFile::createObjectFile(AbsolutePath);572}();573574if (!Obj) {575// TODO: Actually report errors helpfully.576consumeError(Obj.takeError());577return nullptr;578}579580auto S = std::make_shared<DWOFile>();581S->File = std::move(Obj.get());582// Allow multi-threaded access if there is a .dwp file as the CU index and583// TU index might be accessed from multiple threads.584bool ThreadSafe = isThreadSafe();585S->Context = DWARFContext::create(586*S->File.getBinary(), DWARFContext::ProcessDebugRelocations::Ignore,587nullptr, "", WithColor::defaultErrorHandler,588WithColor::defaultWarningHandler, ThreadSafe);589*Entry = S;590auto *Ctxt = S->Context.get();591return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);592}593594bool isThreadSafe() const override { return false; }595596const DenseMap<uint64_t, DWARFTypeUnit *> &getNormalTypeUnitMap() {597if (!NormalTypeUnits) {598NormalTypeUnits.emplace();599for (const auto &U :D.normal_units()) {600if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))601(*NormalTypeUnits)[TU->getTypeHash()] = TU;602}603}604return *NormalTypeUnits;605}606607const DenseMap<uint64_t, DWARFTypeUnit *> &getDWOTypeUnitMap() {608if (!DWOTypeUnits) {609DWOTypeUnits.emplace();610for (const auto &U :D.dwo_units()) {611if (DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(U.get()))612(*DWOTypeUnits)[TU->getTypeHash()] = TU;613}614}615return *DWOTypeUnits;616}617618const DenseMap<uint64_t, DWARFTypeUnit *> &619getTypeUnitMap(bool IsDWO) override {620if (IsDWO)621return getDWOTypeUnitMap();622else623return getNormalTypeUnitMap();624}625626627};628629class ThreadSafeState : public ThreadUnsafeDWARFContextState {630std::recursive_mutex Mutex;631632public:633ThreadSafeState(DWARFContext &DC, std::string &DWP) :634ThreadUnsafeDWARFContextState(DC, DWP) {}635636DWARFUnitVector &getNormalUnits() override {637std::unique_lock<std::recursive_mutex> LockGuard(Mutex);638return ThreadUnsafeDWARFContextState::getNormalUnits();639}640DWARFUnitVector &getDWOUnits(bool Lazy) override {641std::unique_lock<std::recursive_mutex> LockGuard(Mutex);642// We need to not do lazy parsing when we need thread safety as643// DWARFUnitVector, in lazy mode, will slowly add things to itself and644// will cause problems in a multi-threaded environment.645return ThreadUnsafeDWARFContextState::getDWOUnits(false);646}647const DWARFUnitIndex &getCUIndex() override {648std::unique_lock<std::recursive_mutex> LockGuard(Mutex);649return ThreadUnsafeDWARFContextState::getCUIndex();650}651const DWARFDebugAbbrev *getDebugAbbrevDWO() override {652std::unique_lock<std::recursive_mutex> LockGuard(Mutex);653return ThreadUnsafeDWARFContextState::getDebugAbbrevDWO();654}655656const DWARFUnitIndex &getTUIndex() override {657std::unique_lock<std::recursive_mutex> LockGuard(Mutex);658return ThreadUnsafeDWARFContextState::getTUIndex();659}660DWARFGdbIndex &getGdbIndex() override {661std::unique_lock<std::recursive_mutex> LockGuard(Mutex);662return ThreadUnsafeDWARFContextState::getGdbIndex();663}664const DWARFDebugAbbrev *getDebugAbbrev() override {665std::unique_lock<std::recursive_mutex> LockGuard(Mutex);666return ThreadUnsafeDWARFContextState::getDebugAbbrev();667}668const DWARFDebugLoc *getDebugLoc() override {669std::unique_lock<std::recursive_mutex> LockGuard(Mutex);670return ThreadUnsafeDWARFContextState::getDebugLoc();671}672const DWARFDebugAranges *getDebugAranges() override {673std::unique_lock<std::recursive_mutex> LockGuard(Mutex);674return ThreadUnsafeDWARFContextState::getDebugAranges();675}676Expected<const DWARFDebugLine::LineTable *>677getLineTableForUnit(DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) override {678std::unique_lock<std::recursive_mutex> LockGuard(Mutex);679return ThreadUnsafeDWARFContextState::getLineTableForUnit(U, RecoverableErrorHandler);680}681void clearLineTableForUnit(DWARFUnit *U) override {682std::unique_lock<std::recursive_mutex> LockGuard(Mutex);683return ThreadUnsafeDWARFContextState::clearLineTableForUnit(U);684}685Expected<const DWARFDebugFrame *> getDebugFrame() override {686std::unique_lock<std::recursive_mutex> LockGuard(Mutex);687return ThreadUnsafeDWARFContextState::getDebugFrame();688}689Expected<const DWARFDebugFrame *> getEHFrame() override {690std::unique_lock<std::recursive_mutex> LockGuard(Mutex);691return ThreadUnsafeDWARFContextState::getEHFrame();692}693const DWARFDebugMacro *getDebugMacinfo() override {694std::unique_lock<std::recursive_mutex> LockGuard(Mutex);695return ThreadUnsafeDWARFContextState::getDebugMacinfo();696}697const DWARFDebugMacro *getDebugMacinfoDWO() override {698std::unique_lock<std::recursive_mutex> LockGuard(Mutex);699return ThreadUnsafeDWARFContextState::getDebugMacinfoDWO();700}701const DWARFDebugMacro *getDebugMacro() override {702std::unique_lock<std::recursive_mutex> LockGuard(Mutex);703return ThreadUnsafeDWARFContextState::getDebugMacro();704}705const DWARFDebugMacro *getDebugMacroDWO() override {706std::unique_lock<std::recursive_mutex> LockGuard(Mutex);707return ThreadUnsafeDWARFContextState::getDebugMacroDWO();708}709const DWARFDebugNames &getDebugNames() override {710std::unique_lock<std::recursive_mutex> LockGuard(Mutex);711return ThreadUnsafeDWARFContextState::getDebugNames();712}713const AppleAcceleratorTable &getAppleNames() override {714std::unique_lock<std::recursive_mutex> LockGuard(Mutex);715return ThreadUnsafeDWARFContextState::getAppleNames();716}717const AppleAcceleratorTable &getAppleTypes() override {718std::unique_lock<std::recursive_mutex> LockGuard(Mutex);719return ThreadUnsafeDWARFContextState::getAppleTypes();720}721const AppleAcceleratorTable &getAppleNamespaces() override {722std::unique_lock<std::recursive_mutex> LockGuard(Mutex);723return ThreadUnsafeDWARFContextState::getAppleNamespaces();724}725const AppleAcceleratorTable &getAppleObjC() override {726std::unique_lock<std::recursive_mutex> LockGuard(Mutex);727return ThreadUnsafeDWARFContextState::getAppleObjC();728}729std::shared_ptr<DWARFContext>730getDWOContext(StringRef AbsolutePath) override {731std::unique_lock<std::recursive_mutex> LockGuard(Mutex);732return ThreadUnsafeDWARFContextState::getDWOContext(AbsolutePath);733}734735bool isThreadSafe() const override { return true; }736737const DenseMap<uint64_t, DWARFTypeUnit *> &738getTypeUnitMap(bool IsDWO) override {739std::unique_lock<std::recursive_mutex> LockGuard(Mutex);740return ThreadUnsafeDWARFContextState::getTypeUnitMap(IsDWO);741}742};743} // namespace744745DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,746std::string DWPName,747std::function<void(Error)> RecoverableErrorHandler,748std::function<void(Error)> WarningHandler,749bool ThreadSafe)750: DIContext(CK_DWARF),751RecoverableErrorHandler(RecoverableErrorHandler),752WarningHandler(WarningHandler), DObj(std::move(DObj)) {753if (ThreadSafe)754State = std::make_unique<ThreadSafeState>(*this, DWPName);755else756State = std::make_unique<ThreadUnsafeDWARFContextState>(*this, DWPName);757}758759DWARFContext::~DWARFContext() = default;760761/// Dump the UUID load command.762static void dumpUUID(raw_ostream &OS, const ObjectFile &Obj) {763auto *MachO = dyn_cast<MachOObjectFile>(&Obj);764if (!MachO)765return;766for (auto LC : MachO->load_commands()) {767raw_ostream::uuid_t UUID;768if (LC.C.cmd == MachO::LC_UUID) {769if (LC.C.cmdsize < sizeof(UUID) + sizeof(LC.C)) {770OS << "error: UUID load command is too short.\n";771return;772}773OS << "UUID: ";774memcpy(&UUID, LC.Ptr+sizeof(LC.C), sizeof(UUID));775OS.write_uuid(UUID);776Triple T = MachO->getArchTriple();777OS << " (" << T.getArchName() << ')';778OS << ' ' << MachO->getFileName() << '\n';779}780}781}782783using ContributionCollection =784std::vector<std::optional<StrOffsetsContributionDescriptor>>;785786// Collect all the contributions to the string offsets table from all units,787// sort them by their starting offsets and remove duplicates.788static ContributionCollection789collectContributionData(DWARFContext::unit_iterator_range Units) {790ContributionCollection Contributions;791for (const auto &U : Units)792if (const auto &C = U->getStringOffsetsTableContribution())793Contributions.push_back(C);794// Sort the contributions so that any invalid ones are placed at795// the start of the contributions vector. This way they are reported796// first.797llvm::sort(Contributions,798[](const std::optional<StrOffsetsContributionDescriptor> &L,799const std::optional<StrOffsetsContributionDescriptor> &R) {800if (L && R)801return L->Base < R->Base;802return R.has_value();803});804805// Uniquify contributions, as it is possible that units (specifically806// type units in dwo or dwp files) share contributions. We don't want807// to report them more than once.808Contributions.erase(809llvm::unique(810Contributions,811[](const std::optional<StrOffsetsContributionDescriptor> &L,812const std::optional<StrOffsetsContributionDescriptor> &R) {813if (L && R)814return L->Base == R->Base && L->Size == R->Size;815return false;816}),817Contributions.end());818return Contributions;819}820821// Dump a DWARF string offsets section. This may be a DWARF v5 formatted822// string offsets section, where each compile or type unit contributes a823// number of entries (string offsets), with each contribution preceded by824// a header containing size and version number. Alternatively, it may be a825// monolithic series of string offsets, as generated by the pre-DWARF v5826// implementation of split DWARF; however, in that case we still need to827// collect contributions of units because the size of the offsets (4 or 8828// bytes) depends on the format of the referencing unit (DWARF32 or DWARF64).829static void dumpStringOffsetsSection(raw_ostream &OS, DIDumpOptions DumpOpts,830StringRef SectionName,831const DWARFObject &Obj,832const DWARFSection &StringOffsetsSection,833StringRef StringSection,834DWARFContext::unit_iterator_range Units,835bool LittleEndian) {836auto Contributions = collectContributionData(Units);837DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0);838DataExtractor StrData(StringSection, LittleEndian, 0);839uint64_t SectionSize = StringOffsetsSection.Data.size();840uint64_t Offset = 0;841for (auto &Contribution : Contributions) {842// Report an ill-formed contribution.843if (!Contribution) {844OS << "error: invalid contribution to string offsets table in section ."845<< SectionName << ".\n";846return;847}848849dwarf::DwarfFormat Format = Contribution->getFormat();850int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);851uint16_t Version = Contribution->getVersion();852uint64_t ContributionHeader = Contribution->Base;853// In DWARF v5 there is a contribution header that immediately precedes854// the string offsets base (the location we have previously retrieved from855// the CU DIE's DW_AT_str_offsets attribute). The header is located either856// 8 or 16 bytes before the base, depending on the contribution's format.857if (Version >= 5)858ContributionHeader -= Format == DWARF32 ? 8 : 16;859860// Detect overlapping contributions.861if (Offset > ContributionHeader) {862DumpOpts.RecoverableErrorHandler(createStringError(863errc::invalid_argument,864"overlapping contributions to string offsets table in section .%s.",865SectionName.data()));866}867// Report a gap in the table.868if (Offset < ContributionHeader) {869OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);870OS << (ContributionHeader - Offset) << "\n";871}872OS << format("0x%8.8" PRIx64 ": ", ContributionHeader);873// In DWARF v5 the contribution size in the descriptor does not equal874// the originally encoded length (it does not contain the length of the875// version field and the padding, a total of 4 bytes). Add them back in876// for reporting.877OS << "Contribution size = " << (Contribution->Size + (Version < 5 ? 0 : 4))878<< ", Format = " << dwarf::FormatString(Format)879<< ", Version = " << Version << "\n";880881Offset = Contribution->Base;882unsigned EntrySize = Contribution->getDwarfOffsetByteSize();883while (Offset - Contribution->Base < Contribution->Size) {884OS << format("0x%8.8" PRIx64 ": ", Offset);885uint64_t StringOffset =886StrOffsetExt.getRelocatedValue(EntrySize, &Offset);887OS << format("%0*" PRIx64 " ", OffsetDumpWidth, StringOffset);888const char *S = StrData.getCStr(&StringOffset);889if (S)890OS << format("\"%s\"", S);891OS << "\n";892}893}894// Report a gap at the end of the table.895if (Offset < SectionSize) {896OS << format("0x%8.8" PRIx64 ": Gap, length = ", Offset);897OS << (SectionSize - Offset) << "\n";898}899}900901// Dump the .debug_addr section.902static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,903DIDumpOptions DumpOpts, uint16_t Version,904uint8_t AddrSize) {905uint64_t Offset = 0;906while (AddrData.isValidOffset(Offset)) {907DWARFDebugAddrTable AddrTable;908uint64_t TableOffset = Offset;909if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize,910DumpOpts.WarningHandler)) {911DumpOpts.RecoverableErrorHandler(std::move(Err));912// Keep going after an error, if we can, assuming that the length field913// could be read. If it couldn't, stop reading the section.914if (auto TableLength = AddrTable.getFullLength()) {915Offset = TableOffset + *TableLength;916continue;917}918break;919}920AddrTable.dump(OS, DumpOpts);921}922}923924// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).925static void dumpRnglistsSection(926raw_ostream &OS, DWARFDataExtractor &rnglistData,927llvm::function_ref<std::optional<object::SectionedAddress>(uint32_t)>928LookupPooledAddress,929DIDumpOptions DumpOpts) {930uint64_t Offset = 0;931while (rnglistData.isValidOffset(Offset)) {932llvm::DWARFDebugRnglistTable Rnglists;933uint64_t TableOffset = Offset;934if (Error Err = Rnglists.extract(rnglistData, &Offset)) {935DumpOpts.RecoverableErrorHandler(std::move(Err));936uint64_t Length = Rnglists.length();937// Keep going after an error, if we can, assuming that the length field938// could be read. If it couldn't, stop reading the section.939if (Length == 0)940break;941Offset = TableOffset + Length;942} else {943Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts);944}945}946}947948949static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,950DWARFDataExtractor Data, const DWARFObject &Obj,951std::optional<uint64_t> DumpOffset) {952uint64_t Offset = 0;953954while (Data.isValidOffset(Offset)) {955DWARFListTableHeader Header(".debug_loclists", "locations");956if (Error E = Header.extract(Data, &Offset)) {957DumpOpts.RecoverableErrorHandler(std::move(E));958return;959}960961Header.dump(Data, OS, DumpOpts);962963uint64_t EndOffset = Header.length() + Header.getHeaderOffset();964Data.setAddressSize(Header.getAddrSize());965DWARFDebugLoclists Loc(Data, Header.getVersion());966if (DumpOffset) {967if (DumpOffset >= Offset && DumpOffset < EndOffset) {968Offset = *DumpOffset;969Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/std::nullopt, Obj,970nullptr, DumpOpts, /*Indent=*/0);971OS << "\n";972return;973}974} else {975Loc.dumpRange(Offset, EndOffset - Offset, OS, Obj, DumpOpts);976}977Offset = EndOffset;978}979}980981static void dumpPubTableSection(raw_ostream &OS, DIDumpOptions DumpOpts,982DWARFDataExtractor Data, bool GnuStyle) {983DWARFDebugPubTable Table;984Table.extract(Data, GnuStyle, DumpOpts.RecoverableErrorHandler);985Table.dump(OS);986}987988void DWARFContext::dump(989raw_ostream &OS, DIDumpOptions DumpOpts,990std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {991uint64_t DumpType = DumpOpts.DumpType;992993StringRef Extension = sys::path::extension(DObj->getFileName());994bool IsDWO = (Extension == ".dwo") || (Extension == ".dwp");995996// Print UUID header.997const auto *ObjFile = DObj->getFile();998if (DumpType & DIDT_UUID)999dumpUUID(OS, *ObjFile);10001001// Print a header for each explicitly-requested section.1002// Otherwise just print one for non-empty sections.1003// Only print empty .dwo section headers when dumping a .dwo file.1004bool Explicit = DumpType != DIDT_All && !IsDWO;1005bool ExplicitDWO = Explicit && IsDWO;1006auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID,1007StringRef Section) -> std::optional<uint64_t> * {1008unsigned Mask = 1U << ID;1009bool Should = (DumpType & Mask) && (Explicit || !Section.empty());1010if (!Should)1011return nullptr;1012OS << "\n" << Name << " contents:\n";1013return &DumpOffsets[ID];1014};10151016// Dump individual sections.1017if (shouldDump(Explicit, ".debug_abbrev", DIDT_ID_DebugAbbrev,1018DObj->getAbbrevSection()))1019getDebugAbbrev()->dump(OS);1020if (shouldDump(ExplicitDWO, ".debug_abbrev.dwo", DIDT_ID_DebugAbbrev,1021DObj->getAbbrevDWOSection()))1022getDebugAbbrevDWO()->dump(OS);10231024auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {1025OS << '\n' << Name << " contents:\n";1026if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])1027for (const auto &U : Units) {1028U->getDIEForOffset(*DumpOffset)1029.dump(OS, 0, DumpOpts.noImplicitRecursion());1030DWARFDie CUDie = U->getUnitDIE(false);1031DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false);1032if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {1033CUNonSkeletonDie.getDwarfUnit()1034->getDIEForOffset(*DumpOffset)1035.dump(OS, 0, DumpOpts.noImplicitRecursion());1036}1037}1038else1039for (const auto &U : Units)1040U->dump(OS, DumpOpts);1041};1042if ((DumpType & DIDT_DebugInfo)) {1043if (Explicit || getNumCompileUnits())1044dumpDebugInfo(".debug_info", info_section_units());1045if (ExplicitDWO || getNumDWOCompileUnits())1046dumpDebugInfo(".debug_info.dwo", dwo_info_section_units());1047}10481049auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) {1050OS << '\n' << Name << " contents:\n";1051for (const auto &U : Units)1052if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes])1053U->getDIEForOffset(*DumpOffset)1054.dump(OS, 0, DumpOpts.noImplicitRecursion());1055else1056U->dump(OS, DumpOpts);1057};1058if ((DumpType & DIDT_DebugTypes)) {1059if (Explicit || getNumTypeUnits())1060dumpDebugType(".debug_types", types_section_units());1061if (ExplicitDWO || getNumDWOTypeUnits())1062dumpDebugType(".debug_types.dwo", dwo_types_section_units());1063}10641065DIDumpOptions LLDumpOpts = DumpOpts;1066if (LLDumpOpts.Verbose)1067LLDumpOpts.DisplayRawContents = true;10681069if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,1070DObj->getLocSection().Data)) {1071getDebugLoc()->dump(OS, *DObj, LLDumpOpts, *Off);1072}1073if (const auto *Off =1074shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,1075DObj->getLoclistsSection().Data)) {1076DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),10770);1078dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);1079}1080if (const auto *Off =1081shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,1082DObj->getLoclistsDWOSection().Data)) {1083DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),1084isLittleEndian(), 0);1085dumpLoclistsSection(OS, LLDumpOpts, Data, *DObj, *Off);1086}10871088if (const auto *Off =1089shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,1090DObj->getLocDWOSection().Data)) {1091DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),10924);1093DWARFDebugLoclists Loc(Data, /*Version=*/4);1094if (*Off) {1095uint64_t Offset = **Off;1096Loc.dumpLocationList(&Offset, OS,1097/*BaseAddr=*/std::nullopt, *DObj, nullptr,1098LLDumpOpts,1099/*Indent=*/0);1100OS << "\n";1101} else {1102Loc.dumpRange(0, Data.getData().size(), OS, *DObj, LLDumpOpts);1103}1104}11051106if (const std::optional<uint64_t> *Off =1107shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,1108DObj->getFrameSection().Data)) {1109if (Expected<const DWARFDebugFrame *> DF = getDebugFrame())1110(*DF)->dump(OS, DumpOpts, *Off);1111else1112RecoverableErrorHandler(DF.takeError());1113}11141115if (const std::optional<uint64_t> *Off =1116shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,1117DObj->getEHFrameSection().Data)) {1118if (Expected<const DWARFDebugFrame *> DF = getEHFrame())1119(*DF)->dump(OS, DumpOpts, *Off);1120else1121RecoverableErrorHandler(DF.takeError());1122}11231124if (shouldDump(Explicit, ".debug_macro", DIDT_ID_DebugMacro,1125DObj->getMacroSection().Data)) {1126if (auto Macro = getDebugMacro())1127Macro->dump(OS);1128}11291130if (shouldDump(Explicit, ".debug_macro.dwo", DIDT_ID_DebugMacro,1131DObj->getMacroDWOSection())) {1132if (auto MacroDWO = getDebugMacroDWO())1133MacroDWO->dump(OS);1134}11351136if (shouldDump(Explicit, ".debug_macinfo", DIDT_ID_DebugMacro,1137DObj->getMacinfoSection())) {1138if (auto Macinfo = getDebugMacinfo())1139Macinfo->dump(OS);1140}11411142if (shouldDump(Explicit, ".debug_macinfo.dwo", DIDT_ID_DebugMacro,1143DObj->getMacinfoDWOSection())) {1144if (auto MacinfoDWO = getDebugMacinfoDWO())1145MacinfoDWO->dump(OS);1146}11471148if (shouldDump(Explicit, ".debug_aranges", DIDT_ID_DebugAranges,1149DObj->getArangesSection())) {1150uint64_t offset = 0;1151DWARFDataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(),11520);1153DWARFDebugArangeSet set;1154while (arangesData.isValidOffset(offset)) {1155if (Error E =1156set.extract(arangesData, &offset, DumpOpts.WarningHandler)) {1157RecoverableErrorHandler(std::move(E));1158break;1159}1160set.dump(OS);1161}1162}11631164auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,1165DIDumpOptions DumpOpts,1166std::optional<uint64_t> DumpOffset) {1167while (!Parser.done()) {1168if (DumpOffset && Parser.getOffset() != *DumpOffset) {1169Parser.skip(DumpOpts.WarningHandler, DumpOpts.WarningHandler);1170continue;1171}1172OS << "debug_line[" << format("0x%8.8" PRIx64, Parser.getOffset())1173<< "]\n";1174Parser.parseNext(DumpOpts.WarningHandler, DumpOpts.WarningHandler, &OS,1175DumpOpts.Verbose);1176}1177};11781179auto DumpStrSection = [&](StringRef Section) {1180DataExtractor StrData(Section, isLittleEndian(), 0);1181uint64_t Offset = 0;1182uint64_t StrOffset = 0;1183while (StrData.isValidOffset(Offset)) {1184Error Err = Error::success();1185const char *CStr = StrData.getCStr(&Offset, &Err);1186if (Err) {1187DumpOpts.WarningHandler(std::move(Err));1188return;1189}1190OS << format("0x%8.8" PRIx64 ": \"", StrOffset);1191OS.write_escaped(CStr);1192OS << "\"\n";1193StrOffset = Offset;1194}1195};11961197if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine,1198DObj->getLineSection().Data)) {1199DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(),12000);1201DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units());1202DumpLineSection(Parser, DumpOpts, *Off);1203}12041205if (const auto *Off =1206shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine,1207DObj->getLineDWOSection().Data)) {1208DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(),1209isLittleEndian(), 0);1210DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units());1211DumpLineSection(Parser, DumpOpts, *Off);1212}12131214if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex,1215DObj->getCUIndexSection())) {1216getCUIndex().dump(OS);1217}12181219if (shouldDump(Explicit, ".debug_tu_index", DIDT_ID_DebugTUIndex,1220DObj->getTUIndexSection())) {1221getTUIndex().dump(OS);1222}12231224if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr,1225DObj->getStrSection()))1226DumpStrSection(DObj->getStrSection());12271228if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr,1229DObj->getStrDWOSection()))1230DumpStrSection(DObj->getStrDWOSection());12311232if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr,1233DObj->getLineStrSection()))1234DumpStrSection(DObj->getLineStrSection());12351236if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr,1237DObj->getAddrSection().Data)) {1238DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(),1239isLittleEndian(), 0);1240dumpAddrSection(OS, AddrData, DumpOpts, getMaxVersion(), getCUAddrSize());1241}12421243if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges,1244DObj->getRangesSection().Data)) {1245uint8_t savedAddressByteSize = getCUAddrSize();1246DWARFDataExtractor rangesData(*DObj, DObj->getRangesSection(),1247isLittleEndian(), savedAddressByteSize);1248uint64_t offset = 0;1249DWARFDebugRangeList rangeList;1250while (rangesData.isValidOffset(offset)) {1251if (Error E = rangeList.extract(rangesData, &offset)) {1252DumpOpts.RecoverableErrorHandler(std::move(E));1253break;1254}1255rangeList.dump(OS);1256}1257}12581259auto LookupPooledAddress =1260[&](uint32_t Index) -> std::optional<SectionedAddress> {1261const auto &CUs = compile_units();1262auto I = CUs.begin();1263if (I == CUs.end())1264return std::nullopt;1265return (*I)->getAddrOffsetSectionItem(Index);1266};12671268if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists,1269DObj->getRnglistsSection().Data)) {1270DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(),1271isLittleEndian(), 0);1272dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);1273}12741275if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists,1276DObj->getRnglistsDWOSection().Data)) {1277DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(),1278isLittleEndian(), 0);1279dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts);1280}12811282if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames,1283DObj->getPubnamesSection().Data)) {1284DWARFDataExtractor PubTableData(*DObj, DObj->getPubnamesSection(),1285isLittleEndian(), 0);1286dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);1287}12881289if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes,1290DObj->getPubtypesSection().Data)) {1291DWARFDataExtractor PubTableData(*DObj, DObj->getPubtypesSection(),1292isLittleEndian(), 0);1293dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/false);1294}12951296if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames,1297DObj->getGnuPubnamesSection().Data)) {1298DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubnamesSection(),1299isLittleEndian(), 0);1300dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);1301}13021303if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes,1304DObj->getGnuPubtypesSection().Data)) {1305DWARFDataExtractor PubTableData(*DObj, DObj->getGnuPubtypesSection(),1306isLittleEndian(), 0);1307dumpPubTableSection(OS, DumpOpts, PubTableData, /*GnuStyle=*/true);1308}13091310if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets,1311DObj->getStrOffsetsSection().Data))1312dumpStringOffsetsSection(1313OS, DumpOpts, "debug_str_offsets", *DObj, DObj->getStrOffsetsSection(),1314DObj->getStrSection(), normal_units(), isLittleEndian());1315if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets,1316DObj->getStrOffsetsDWOSection().Data))1317dumpStringOffsetsSection(OS, DumpOpts, "debug_str_offsets.dwo", *DObj,1318DObj->getStrOffsetsDWOSection(),1319DObj->getStrDWOSection(), dwo_units(),1320isLittleEndian());13211322if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex,1323DObj->getGdbIndexSection())) {1324getGdbIndex().dump(OS);1325}13261327if (shouldDump(Explicit, ".apple_names", DIDT_ID_AppleNames,1328DObj->getAppleNamesSection().Data))1329getAppleNames().dump(OS);13301331if (shouldDump(Explicit, ".apple_types", DIDT_ID_AppleTypes,1332DObj->getAppleTypesSection().Data))1333getAppleTypes().dump(OS);13341335if (shouldDump(Explicit, ".apple_namespaces", DIDT_ID_AppleNamespaces,1336DObj->getAppleNamespacesSection().Data))1337getAppleNamespaces().dump(OS);13381339if (shouldDump(Explicit, ".apple_objc", DIDT_ID_AppleObjC,1340DObj->getAppleObjCSection().Data))1341getAppleObjC().dump(OS);1342if (shouldDump(Explicit, ".debug_names", DIDT_ID_DebugNames,1343DObj->getNamesSection().Data))1344getDebugNames().dump(OS);1345}13461347DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version, uint64_t Hash,1348bool IsDWO) {1349DWARFUnitVector &DWOUnits = State->getDWOUnits();1350if (const auto &TUI = getTUIndex()) {1351if (const auto *R = TUI.getFromHash(Hash))1352return dyn_cast_or_null<DWARFTypeUnit>(1353DWOUnits.getUnitForIndexEntry(*R));1354return nullptr;1355}1356return State->getTypeUnitMap(IsDWO).lookup(Hash);1357}13581359DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {1360DWARFUnitVector &DWOUnits = State->getDWOUnits(LazyParse);13611362if (const auto &CUI = getCUIndex()) {1363if (const auto *R = CUI.getFromHash(Hash))1364return dyn_cast_or_null<DWARFCompileUnit>(1365DWOUnits.getUnitForIndexEntry(*R));1366return nullptr;1367}13681369// If there's no index, just search through the CUs in the DWO - there's1370// probably only one unless this is something like LTO - though an in-process1371// built/cached lookup table could be used in that case to improve repeated1372// lookups of different CUs in the DWO.1373for (const auto &DWOCU : dwo_compile_units()) {1374// Might not have parsed DWO ID yet.1375if (!DWOCU->getDWOId()) {1376if (std::optional<uint64_t> DWOId =1377toUnsigned(DWOCU->getUnitDIE().find(DW_AT_GNU_dwo_id)))1378DWOCU->setDWOId(*DWOId);1379else1380// No DWO ID?1381continue;1382}1383if (DWOCU->getDWOId() == Hash)1384return dyn_cast<DWARFCompileUnit>(DWOCU.get());1385}1386return nullptr;1387}13881389DWARFDie DWARFContext::getDIEForOffset(uint64_t Offset) {1390if (auto *CU = State->getNormalUnits().getUnitForOffset(Offset))1391return CU->getDIEForOffset(Offset);1392return DWARFDie();1393}13941395bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {1396bool Success = true;1397DWARFVerifier verifier(OS, *this, DumpOpts);13981399Success &= verifier.handleDebugAbbrev();1400if (DumpOpts.DumpType & DIDT_DebugCUIndex)1401Success &= verifier.handleDebugCUIndex();1402if (DumpOpts.DumpType & DIDT_DebugTUIndex)1403Success &= verifier.handleDebugTUIndex();1404if (DumpOpts.DumpType & DIDT_DebugInfo)1405Success &= verifier.handleDebugInfo();1406if (DumpOpts.DumpType & DIDT_DebugLine)1407Success &= verifier.handleDebugLine();1408if (DumpOpts.DumpType & DIDT_DebugStrOffsets)1409Success &= verifier.handleDebugStrOffsets();1410Success &= verifier.handleAccelTables();1411verifier.summarize();1412return Success;1413}14141415const DWARFUnitIndex &DWARFContext::getCUIndex() {1416return State->getCUIndex();1417}14181419const DWARFUnitIndex &DWARFContext::getTUIndex() {1420return State->getTUIndex();1421}14221423DWARFGdbIndex &DWARFContext::getGdbIndex() {1424return State->getGdbIndex();1425}14261427const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {1428return State->getDebugAbbrev();1429}14301431const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {1432return State->getDebugAbbrevDWO();1433}14341435const DWARFDebugLoc *DWARFContext::getDebugLoc() {1436return State->getDebugLoc();1437}14381439const DWARFDebugAranges *DWARFContext::getDebugAranges() {1440return State->getDebugAranges();1441}14421443Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() {1444return State->getDebugFrame();1445}14461447Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() {1448return State->getEHFrame();1449}14501451const DWARFDebugMacro *DWARFContext::getDebugMacro() {1452return State->getDebugMacro();1453}14541455const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {1456return State->getDebugMacroDWO();1457}14581459const DWARFDebugMacro *DWARFContext::getDebugMacinfo() {1460return State->getDebugMacinfo();1461}14621463const DWARFDebugMacro *DWARFContext::getDebugMacinfoDWO() {1464return State->getDebugMacinfoDWO();1465}146614671468const DWARFDebugNames &DWARFContext::getDebugNames() {1469return State->getDebugNames();1470}14711472const AppleAcceleratorTable &DWARFContext::getAppleNames() {1473return State->getAppleNames();1474}14751476const AppleAcceleratorTable &DWARFContext::getAppleTypes() {1477return State->getAppleTypes();1478}14791480const AppleAcceleratorTable &DWARFContext::getAppleNamespaces() {1481return State->getAppleNamespaces();1482}14831484const AppleAcceleratorTable &DWARFContext::getAppleObjC() {1485return State->getAppleObjC();1486}14871488const DWARFDebugLine::LineTable *1489DWARFContext::getLineTableForUnit(DWARFUnit *U) {1490Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable =1491getLineTableForUnit(U, WarningHandler);1492if (!ExpectedLineTable) {1493WarningHandler(ExpectedLineTable.takeError());1494return nullptr;1495}1496return *ExpectedLineTable;1497}14981499Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(1500DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {1501return State->getLineTableForUnit(U, RecoverableErrorHandler);1502}15031504void DWARFContext::clearLineTableForUnit(DWARFUnit *U) {1505return State->clearLineTableForUnit(U);1506}15071508DWARFUnitVector &DWARFContext::getDWOUnits(bool Lazy) {1509return State->getDWOUnits(Lazy);1510}15111512DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint64_t Offset) {1513return dyn_cast_or_null<DWARFCompileUnit>(1514State->getNormalUnits().getUnitForOffset(Offset));1515}15161517DWARFCompileUnit *DWARFContext::getCompileUnitForCodeAddress(uint64_t Address) {1518uint64_t CUOffset = getDebugAranges()->findAddress(Address);1519return getCompileUnitForOffset(CUOffset);1520}15211522DWARFCompileUnit *DWARFContext::getCompileUnitForDataAddress(uint64_t Address) {1523uint64_t CUOffset = getDebugAranges()->findAddress(Address);1524if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset))1525return OffsetCU;15261527// Global variables are often missed by the above search, for one of two1528// reasons:1529// 1. .debug_aranges may not include global variables. On clang, it seems we1530// put the globals in the aranges, but this isn't true for gcc.1531// 2. Even if the global variable is in a .debug_arange, global variables1532// may not be captured in the [start, end) addresses described by the1533// parent compile unit.1534//1535// So, we walk the CU's and their child DI's manually, looking for the1536// specific global variable.1537for (std::unique_ptr<DWARFUnit> &CU : compile_units()) {1538if (CU->getVariableForAddress(Address)) {1539return static_cast<DWARFCompileUnit *>(CU.get());1540}1541}1542return nullptr;1543}15441545DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address,1546bool CheckDWO) {1547DIEsForAddress Result;15481549DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address);1550if (!CU)1551return Result;15521553if (CheckDWO) {1554// We were asked to check the DWO file and this debug information is more1555// complete that any information in the skeleton compile unit, so search the1556// DWO first to see if we have a match.1557DWARFDie CUDie = CU->getUnitDIE(false);1558DWARFDie CUDwoDie = CU->getNonSkeletonUnitDIE(false);1559if (CheckDWO && CUDwoDie && CUDie != CUDwoDie) {1560// We have a DWO file, lets search it.1561DWARFCompileUnit *CUDwo =1562dyn_cast_or_null<DWARFCompileUnit>(CUDwoDie.getDwarfUnit());1563if (CUDwo) {1564Result.FunctionDIE = CUDwo->getSubroutineForAddress(Address);1565if (Result.FunctionDIE)1566Result.CompileUnit = CUDwo;1567}1568}1569}15701571// Search the normal DWARF if we didn't find a match in the DWO file or if1572// we didn't check the DWO file above.1573if (!Result) {1574Result.CompileUnit = CU;1575Result.FunctionDIE = CU->getSubroutineForAddress(Address);1576}15771578std::vector<DWARFDie> Worklist;1579Worklist.push_back(Result.FunctionDIE);1580while (!Worklist.empty()) {1581DWARFDie DIE = Worklist.back();1582Worklist.pop_back();15831584if (!DIE.isValid())1585continue;15861587if (DIE.getTag() == DW_TAG_lexical_block &&1588DIE.addressRangeContainsAddress(Address)) {1589Result.BlockDIE = DIE;1590break;1591}15921593append_range(Worklist, DIE);1594}15951596return Result;1597}15981599/// TODO: change input parameter from "uint64_t Address"1600/// into "SectionedAddress Address"1601static bool getFunctionNameAndStartLineForAddress(1602DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind,1603DILineInfoSpecifier::FileLineInfoKind FileNameKind,1604std::string &FunctionName, std::string &StartFile, uint32_t &StartLine,1605std::optional<uint64_t> &StartAddress) {1606// The address may correspond to instruction in some inlined function,1607// so we have to build the chain of inlined functions and take the1608// name of the topmost function in it.1609SmallVector<DWARFDie, 4> InlinedChain;1610CU->getInlinedChainForAddress(Address, InlinedChain);1611if (InlinedChain.empty())1612return false;16131614const DWARFDie &DIE = InlinedChain[0];1615bool FoundResult = false;1616const char *Name = nullptr;1617if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {1618FunctionName = Name;1619FoundResult = true;1620}1621std::string DeclFile = DIE.getDeclFile(FileNameKind);1622if (!DeclFile.empty()) {1623StartFile = DeclFile;1624FoundResult = true;1625}1626if (auto DeclLineResult = DIE.getDeclLine()) {1627StartLine = DeclLineResult;1628FoundResult = true;1629}1630if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc)))1631StartAddress = LowPcAddr->Address;1632return FoundResult;1633}16341635static std::optional<int64_t>1636getExpressionFrameOffset(ArrayRef<uint8_t> Expr,1637std::optional<unsigned> FrameBaseReg) {1638if (!Expr.empty() &&1639(Expr[0] == DW_OP_fbreg ||1640(FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {1641unsigned Count;1642int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());1643// A single DW_OP_fbreg or DW_OP_breg.1644if (Expr.size() == Count + 1)1645return Offset;1646// Same + DW_OP_deref (Fortran arrays look like this).1647if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)1648return Offset;1649// Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)1650}1651return std::nullopt;1652}16531654void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,1655DWARFDie Die, std::vector<DILocal> &Result) {1656if (Die.getTag() == DW_TAG_variable ||1657Die.getTag() == DW_TAG_formal_parameter) {1658DILocal Local;1659if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))1660Local.FunctionName = Name;16611662std::optional<unsigned> FrameBaseReg;1663if (auto FrameBase = Subprogram.find(DW_AT_frame_base))1664if (std::optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())1665if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&1666(*Expr)[0] <= DW_OP_reg31) {1667FrameBaseReg = (*Expr)[0] - DW_OP_reg0;1668}16691670if (Expected<std::vector<DWARFLocationExpression>> Loc =1671Die.getLocations(DW_AT_location)) {1672for (const auto &Entry : *Loc) {1673if (std::optional<int64_t> FrameOffset =1674getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {1675Local.FrameOffset = *FrameOffset;1676break;1677}1678}1679} else {1680// FIXME: missing DW_AT_location is OK here, but other errors should be1681// reported to the user.1682consumeError(Loc.takeError());1683}16841685if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))1686Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();16871688if (auto Origin =1689Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))1690Die = Origin;1691if (auto NameAttr = Die.find(DW_AT_name))1692if (std::optional<const char *> Name = dwarf::toString(*NameAttr))1693Local.Name = *Name;1694if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))1695Local.Size = Type.getTypeSize(getCUAddrSize());1696if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {1697if (const auto *LT = CU->getContext().getLineTableForUnit(CU))1698LT->getFileNameByIndex(1699*DeclFileAttr->getAsUnsignedConstant(), CU->getCompilationDir(),1700DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,1701Local.DeclFile);1702}1703if (auto DeclLineAttr = Die.find(DW_AT_decl_line))1704Local.DeclLine = *DeclLineAttr->getAsUnsignedConstant();17051706Result.push_back(Local);1707return;1708}17091710if (Die.getTag() == DW_TAG_inlined_subroutine)1711if (auto Origin =1712Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))1713Subprogram = Origin;17141715for (auto Child : Die)1716addLocalsForDie(CU, Subprogram, Child, Result);1717}17181719std::vector<DILocal>1720DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {1721std::vector<DILocal> Result;1722DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);1723if (!CU)1724return Result;17251726DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);1727if (Subprogram.isValid())1728addLocalsForDie(CU, Subprogram, Subprogram, Result);1729return Result;1730}17311732DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,1733DILineInfoSpecifier Spec) {1734DILineInfo Result;1735DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);1736if (!CU)1737return Result;17381739getFunctionNameAndStartLineForAddress(1740CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName,1741Result.StartFileName, Result.StartLine, Result.StartAddress);1742if (Spec.FLIKind != FileLineInfoKind::None) {1743if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {1744LineTable->getFileLineInfoForAddress(1745{Address.Address, Address.SectionIndex}, CU->getCompilationDir(),1746Spec.FLIKind, Result);1747}1748}17491750return Result;1751}17521753DILineInfo1754DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) {1755DILineInfo Result;1756DWARFCompileUnit *CU = getCompileUnitForDataAddress(Address.Address);1757if (!CU)1758return Result;17591760if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) {1761Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath);1762Result.Line = Die.getDeclLine();1763}17641765return Result;1766}17671768DILineInfoTable DWARFContext::getLineInfoForAddressRange(1769object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {1770DILineInfoTable Lines;1771DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);1772if (!CU)1773return Lines;17741775uint32_t StartLine = 0;1776std::string StartFileName;1777std::string FunctionName(DILineInfo::BadString);1778std::optional<uint64_t> StartAddress;1779getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,1780Spec.FLIKind, FunctionName,1781StartFileName, StartLine, StartAddress);17821783// If the Specifier says we don't need FileLineInfo, just1784// return the top-most function at the starting address.1785if (Spec.FLIKind == FileLineInfoKind::None) {1786DILineInfo Result;1787Result.FunctionName = FunctionName;1788Result.StartFileName = StartFileName;1789Result.StartLine = StartLine;1790Result.StartAddress = StartAddress;1791Lines.push_back(std::make_pair(Address.Address, Result));1792return Lines;1793}17941795const DWARFLineTable *LineTable = getLineTableForUnit(CU);17961797// Get the index of row we're looking for in the line table.1798std::vector<uint32_t> RowVector;1799if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},1800Size, RowVector)) {1801return Lines;1802}18031804for (uint32_t RowIndex : RowVector) {1805// Take file number and line/column from the row.1806const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];1807DILineInfo Result;1808LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),1809Spec.FLIKind, Result.FileName);1810Result.FunctionName = FunctionName;1811Result.Line = Row.Line;1812Result.Column = Row.Column;1813Result.StartFileName = StartFileName;1814Result.StartLine = StartLine;1815Result.StartAddress = StartAddress;1816Lines.push_back(std::make_pair(Row.Address.Address, Result));1817}18181819return Lines;1820}18211822DIInliningInfo1823DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,1824DILineInfoSpecifier Spec) {1825DIInliningInfo InliningInfo;18261827DWARFCompileUnit *CU = getCompileUnitForCodeAddress(Address.Address);1828if (!CU)1829return InliningInfo;18301831const DWARFLineTable *LineTable = nullptr;1832SmallVector<DWARFDie, 4> InlinedChain;1833CU->getInlinedChainForAddress(Address.Address, InlinedChain);1834if (InlinedChain.size() == 0) {1835// If there is no DIE for address (e.g. it is in unavailable .dwo file),1836// try to at least get file/line info from symbol table.1837if (Spec.FLIKind != FileLineInfoKind::None) {1838DILineInfo Frame;1839LineTable = getLineTableForUnit(CU);1840if (LineTable && LineTable->getFileLineInfoForAddress(1841{Address.Address, Address.SectionIndex},1842CU->getCompilationDir(), Spec.FLIKind, Frame))1843InliningInfo.addFrame(Frame);1844}1845return InliningInfo;1846}18471848uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0;1849for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {1850DWARFDie &FunctionDIE = InlinedChain[i];1851DILineInfo Frame;1852// Get function name if necessary.1853if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))1854Frame.FunctionName = Name;1855if (auto DeclLineResult = FunctionDIE.getDeclLine())1856Frame.StartLine = DeclLineResult;1857Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind);1858if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc)))1859Frame.StartAddress = LowPcAddr->Address;1860if (Spec.FLIKind != FileLineInfoKind::None) {1861if (i == 0) {1862// For the topmost frame, initialize the line table of this1863// compile unit and fetch file/line info from it.1864LineTable = getLineTableForUnit(CU);1865// For the topmost routine, get file/line info from line table.1866if (LineTable)1867LineTable->getFileLineInfoForAddress(1868{Address.Address, Address.SectionIndex}, CU->getCompilationDir(),1869Spec.FLIKind, Frame);1870} else {1871// Otherwise, use call file, call line and call column from1872// previous DIE in inlined chain.1873if (LineTable)1874LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),1875Spec.FLIKind, Frame.FileName);1876Frame.Line = CallLine;1877Frame.Column = CallColumn;1878Frame.Discriminator = CallDiscriminator;1879}1880// Get call file/line/column of a current DIE.1881if (i + 1 < n) {1882FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn,1883CallDiscriminator);1884}1885}1886InliningInfo.addFrame(Frame);1887}1888return InliningInfo;1889}18901891std::shared_ptr<DWARFContext>1892DWARFContext::getDWOContext(StringRef AbsolutePath) {1893return State->getDWOContext(AbsolutePath);1894}18951896static Error createError(const Twine &Reason, llvm::Error E) {1897return make_error<StringError>(Reason + toString(std::move(E)),1898inconvertibleErrorCode());1899}19001901/// SymInfo contains information about symbol: it's address1902/// and section index which is -1LL for absolute symbols.1903struct SymInfo {1904uint64_t Address;1905uint64_t SectionIndex;1906};19071908/// Returns the address of symbol relocation used against and a section index.1909/// Used for futher relocations computation. Symbol's section load address is1910static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,1911const RelocationRef &Reloc,1912const LoadedObjectInfo *L,1913std::map<SymbolRef, SymInfo> &Cache) {1914SymInfo Ret = {0, (uint64_t)-1LL};1915object::section_iterator RSec = Obj.section_end();1916object::symbol_iterator Sym = Reloc.getSymbol();19171918std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();1919// First calculate the address of the symbol or section as it appears1920// in the object file1921if (Sym != Obj.symbol_end()) {1922bool New;1923std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});1924if (!New)1925return CacheIt->second;19261927Expected<uint64_t> SymAddrOrErr = Sym->getAddress();1928if (!SymAddrOrErr)1929return createError("failed to compute symbol address: ",1930SymAddrOrErr.takeError());19311932// Also remember what section this symbol is in for later1933auto SectOrErr = Sym->getSection();1934if (!SectOrErr)1935return createError("failed to get symbol section: ",1936SectOrErr.takeError());19371938RSec = *SectOrErr;1939Ret.Address = *SymAddrOrErr;1940} else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {1941RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());1942Ret.Address = RSec->getAddress();1943}19441945if (RSec != Obj.section_end())1946Ret.SectionIndex = RSec->getIndex();19471948// If we are given load addresses for the sections, we need to adjust:1949// SymAddr = (Address of Symbol Or Section in File) -1950// (Address of Section in File) +1951// (Load Address of Section)1952// RSec is now either the section being targeted or the section1953// containing the symbol being targeted. In either case,1954// we need to perform the same computation.1955if (L && RSec != Obj.section_end())1956if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))1957Ret.Address += SectionLoadAddress - RSec->getAddress();19581959if (CacheIt != Cache.end())1960CacheIt->second = Ret;19611962return Ret;1963}19641965static bool isRelocScattered(const object::ObjectFile &Obj,1966const RelocationRef &Reloc) {1967const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);1968if (!MachObj)1969return false;1970// MachO also has relocations that point to sections and1971// scattered relocations.1972auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());1973return MachObj->isRelocationScattered(RelocInfo);1974}19751976namespace {1977struct DWARFSectionMap final : public DWARFSection {1978RelocAddrMap Relocs;1979};19801981class DWARFObjInMemory final : public DWARFObject {1982bool IsLittleEndian;1983uint8_t AddressSize;1984StringRef FileName;1985const object::ObjectFile *Obj = nullptr;1986std::vector<SectionName> SectionNames;19871988using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap,1989std::map<object::SectionRef, unsigned>>;19901991InfoSectionMap InfoSections;1992InfoSectionMap TypesSections;1993InfoSectionMap InfoDWOSections;1994InfoSectionMap TypesDWOSections;19951996DWARFSectionMap LocSection;1997DWARFSectionMap LoclistsSection;1998DWARFSectionMap LoclistsDWOSection;1999DWARFSectionMap LineSection;2000DWARFSectionMap RangesSection;2001DWARFSectionMap RnglistsSection;2002DWARFSectionMap StrOffsetsSection;2003DWARFSectionMap LineDWOSection;2004DWARFSectionMap FrameSection;2005DWARFSectionMap EHFrameSection;2006DWARFSectionMap LocDWOSection;2007DWARFSectionMap StrOffsetsDWOSection;2008DWARFSectionMap RangesDWOSection;2009DWARFSectionMap RnglistsDWOSection;2010DWARFSectionMap AddrSection;2011DWARFSectionMap AppleNamesSection;2012DWARFSectionMap AppleTypesSection;2013DWARFSectionMap AppleNamespacesSection;2014DWARFSectionMap AppleObjCSection;2015DWARFSectionMap NamesSection;2016DWARFSectionMap PubnamesSection;2017DWARFSectionMap PubtypesSection;2018DWARFSectionMap GnuPubnamesSection;2019DWARFSectionMap GnuPubtypesSection;2020DWARFSectionMap MacroSection;20212022DWARFSectionMap *mapNameToDWARFSection(StringRef Name) {2023return StringSwitch<DWARFSectionMap *>(Name)2024.Case("debug_loc", &LocSection)2025.Case("debug_loclists", &LoclistsSection)2026.Case("debug_loclists.dwo", &LoclistsDWOSection)2027.Case("debug_line", &LineSection)2028.Case("debug_frame", &FrameSection)2029.Case("eh_frame", &EHFrameSection)2030.Case("debug_str_offsets", &StrOffsetsSection)2031.Case("debug_ranges", &RangesSection)2032.Case("debug_rnglists", &RnglistsSection)2033.Case("debug_loc.dwo", &LocDWOSection)2034.Case("debug_line.dwo", &LineDWOSection)2035.Case("debug_names", &NamesSection)2036.Case("debug_rnglists.dwo", &RnglistsDWOSection)2037.Case("debug_str_offsets.dwo", &StrOffsetsDWOSection)2038.Case("debug_addr", &AddrSection)2039.Case("apple_names", &AppleNamesSection)2040.Case("debug_pubnames", &PubnamesSection)2041.Case("debug_pubtypes", &PubtypesSection)2042.Case("debug_gnu_pubnames", &GnuPubnamesSection)2043.Case("debug_gnu_pubtypes", &GnuPubtypesSection)2044.Case("apple_types", &AppleTypesSection)2045.Case("apple_namespaces", &AppleNamespacesSection)2046.Case("apple_namespac", &AppleNamespacesSection)2047.Case("apple_objc", &AppleObjCSection)2048.Case("debug_macro", &MacroSection)2049.Default(nullptr);2050}20512052StringRef AbbrevSection;2053StringRef ArangesSection;2054StringRef StrSection;2055StringRef MacinfoSection;2056StringRef MacinfoDWOSection;2057StringRef MacroDWOSection;2058StringRef AbbrevDWOSection;2059StringRef StrDWOSection;2060StringRef CUIndexSection;2061StringRef GdbIndexSection;2062StringRef TUIndexSection;2063StringRef LineStrSection;20642065// A deque holding section data whose iterators are not invalidated when2066// new decompressed sections are inserted at the end.2067std::deque<SmallString<0>> UncompressedSections;20682069StringRef *mapSectionToMember(StringRef Name) {2070if (DWARFSection *Sec = mapNameToDWARFSection(Name))2071return &Sec->Data;2072return StringSwitch<StringRef *>(Name)2073.Case("debug_abbrev", &AbbrevSection)2074.Case("debug_aranges", &ArangesSection)2075.Case("debug_str", &StrSection)2076.Case("debug_macinfo", &MacinfoSection)2077.Case("debug_macinfo.dwo", &MacinfoDWOSection)2078.Case("debug_macro.dwo", &MacroDWOSection)2079.Case("debug_abbrev.dwo", &AbbrevDWOSection)2080.Case("debug_str.dwo", &StrDWOSection)2081.Case("debug_cu_index", &CUIndexSection)2082.Case("debug_tu_index", &TUIndexSection)2083.Case("gdb_index", &GdbIndexSection)2084.Case("debug_line_str", &LineStrSection)2085// Any more debug info sections go here.2086.Default(nullptr);2087}20882089/// If Sec is compressed section, decompresses and updates its contents2090/// provided by Data. Otherwise leaves it unchanged.2091Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,2092StringRef &Data) {2093if (!Sec.isCompressed())2094return Error::success();20952096Expected<Decompressor> Decompressor =2097Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8);2098if (!Decompressor)2099return Decompressor.takeError();21002101SmallString<0> Out;2102if (auto Err = Decompressor->resizeAndDecompress(Out))2103return Err;21042105UncompressedSections.push_back(std::move(Out));2106Data = UncompressedSections.back();21072108return Error::success();2109}21102111public:2112DWARFObjInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,2113uint8_t AddrSize, bool IsLittleEndian)2114: IsLittleEndian(IsLittleEndian) {2115for (const auto &SecIt : Sections) {2116if (StringRef *SectionData = mapSectionToMember(SecIt.first()))2117*SectionData = SecIt.second->getBuffer();2118else if (SecIt.first() == "debug_info")2119// Find debug_info and debug_types data by section rather than name as2120// there are multiple, comdat grouped, of these sections.2121InfoSections[SectionRef()].Data = SecIt.second->getBuffer();2122else if (SecIt.first() == "debug_info.dwo")2123InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer();2124else if (SecIt.first() == "debug_types")2125TypesSections[SectionRef()].Data = SecIt.second->getBuffer();2126else if (SecIt.first() == "debug_types.dwo")2127TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer();2128}2129}2130DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L,2131function_ref<void(Error)> HandleError,2132function_ref<void(Error)> HandleWarning,2133DWARFContext::ProcessDebugRelocations RelocAction)2134: IsLittleEndian(Obj.isLittleEndian()),2135AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()),2136Obj(&Obj) {21372138StringMap<unsigned> SectionAmountMap;2139for (const SectionRef &Section : Obj.sections()) {2140StringRef Name;2141if (auto NameOrErr = Section.getName())2142Name = *NameOrErr;2143else2144consumeError(NameOrErr.takeError());21452146++SectionAmountMap[Name];2147SectionNames.push_back({ Name, true });21482149// Skip BSS and Virtual sections, they aren't interesting.2150if (Section.isBSS() || Section.isVirtual())2151continue;21522153// Skip sections stripped by dsymutil.2154if (Section.isStripped())2155continue;21562157StringRef Data;2158Expected<section_iterator> SecOrErr = Section.getRelocatedSection();2159if (!SecOrErr) {2160HandleError(createError("failed to get relocated section: ",2161SecOrErr.takeError()));2162continue;2163}21642165// Try to obtain an already relocated version of this section.2166// Else use the unrelocated section from the object file. We'll have to2167// apply relocations ourselves later.2168section_iterator RelocatedSection =2169Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end();2170if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {2171Expected<StringRef> E = Section.getContents();2172if (E)2173Data = *E;2174else2175// maybeDecompress below will error.2176consumeError(E.takeError());2177}21782179if (auto Err = maybeDecompress(Section, Name, Data)) {2180HandleError(createError("failed to decompress '" + Name + "', ",2181std::move(Err)));2182continue;2183}21842185// Map platform specific debug section names to DWARF standard section2186// names.2187Name = Name.substr(Name.find_first_not_of("._"));2188Name = Obj.mapDebugSectionName(Name);21892190if (StringRef *SectionData = mapSectionToMember(Name)) {2191*SectionData = Data;2192if (Name == "debug_ranges") {2193// FIXME: Use the other dwo range section when we emit it.2194RangesDWOSection.Data = Data;2195} else if (Name == "debug_frame" || Name == "eh_frame") {2196if (DWARFSection *S = mapNameToDWARFSection(Name))2197S->Address = Section.getAddress();2198}2199} else if (InfoSectionMap *Sections =2200StringSwitch<InfoSectionMap *>(Name)2201.Case("debug_info", &InfoSections)2202.Case("debug_info.dwo", &InfoDWOSections)2203.Case("debug_types", &TypesSections)2204.Case("debug_types.dwo", &TypesDWOSections)2205.Default(nullptr)) {2206// Find debug_info and debug_types data by section rather than name as2207// there are multiple, comdat grouped, of these sections.2208DWARFSectionMap &S = (*Sections)[Section];2209S.Data = Data;2210}22112212if (RelocatedSection == Obj.section_end() ||2213(RelocAction == DWARFContext::ProcessDebugRelocations::Ignore))2214continue;22152216StringRef RelSecName;2217if (auto NameOrErr = RelocatedSection->getName())2218RelSecName = *NameOrErr;2219else2220consumeError(NameOrErr.takeError());22212222// If the section we're relocating was relocated already by the JIT,2223// then we used the relocated version above, so we do not need to process2224// relocations for it now.2225StringRef RelSecData;2226if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))2227continue;22282229// In Mach-o files, the relocations do not need to be applied if2230// there is no load offset to apply. The value read at the2231// relocation point already factors in the section address2232// (actually applying the relocations will produce wrong results2233// as the section address will be added twice).2234if (!L && isa<MachOObjectFile>(&Obj))2235continue;22362237if (!Section.relocations().empty() && Name.ends_with(".dwo") &&2238RelSecName.starts_with(".debug")) {2239HandleWarning(createError("unexpected relocations for dwo section '" +2240RelSecName + "'"));2241}22422243// TODO: Add support for relocations in other sections as needed.2244// Record relocations for the debug_info and debug_line sections.2245RelSecName = RelSecName.substr(RelSecName.find_first_not_of("._"));2246DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName);2247RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr;2248if (!Map) {2249// Find debug_info and debug_types relocs by section rather than name2250// as there are multiple, comdat grouped, of these sections.2251if (RelSecName == "debug_info")2252Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection])2253.Relocs;2254else if (RelSecName == "debug_types")2255Map =2256&static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection])2257.Relocs;2258else2259continue;2260}22612262if (Section.relocation_begin() == Section.relocation_end())2263continue;22642265// Symbol to [address, section index] cache mapping.2266std::map<SymbolRef, SymInfo> AddrCache;2267SupportsRelocation Supports;2268RelocationResolver Resolver;2269std::tie(Supports, Resolver) = getRelocationResolver(Obj);2270for (const RelocationRef &Reloc : Section.relocations()) {2271// FIXME: it's not clear how to correctly handle scattered2272// relocations.2273if (isRelocScattered(Obj, Reloc))2274continue;22752276Expected<SymInfo> SymInfoOrErr =2277getSymbolInfo(Obj, Reloc, L, AddrCache);2278if (!SymInfoOrErr) {2279HandleError(SymInfoOrErr.takeError());2280continue;2281}22822283// Check if Resolver can handle this relocation type early so as not to2284// handle invalid cases in DWARFDataExtractor.2285//2286// TODO Don't store Resolver in every RelocAddrEntry.2287if (Supports && Supports(Reloc.getType())) {2288auto I = Map->try_emplace(2289Reloc.getOffset(),2290RelocAddrEntry{2291SymInfoOrErr->SectionIndex, Reloc, SymInfoOrErr->Address,2292std::optional<object::RelocationRef>(), 0, Resolver});2293// If we didn't successfully insert that's because we already had a2294// relocation for that offset. Store it as a second relocation in the2295// same RelocAddrEntry instead.2296if (!I.second) {2297RelocAddrEntry &entry = I.first->getSecond();2298if (entry.Reloc2) {2299HandleError(createError(2300"At most two relocations per offset are supported"));2301}2302entry.Reloc2 = Reloc;2303entry.SymbolValue2 = SymInfoOrErr->Address;2304}2305} else {2306SmallString<32> Type;2307Reloc.getTypeName(Type);2308// FIXME: Support more relocations & change this to an error2309HandleWarning(2310createError("failed to compute relocation: " + Type + ", ",2311errorCodeToError(object_error::parse_failed)));2312}2313}2314}23152316for (SectionName &S : SectionNames)2317if (SectionAmountMap[S.Name] > 1)2318S.IsNameUnique = false;2319}23202321std::optional<RelocAddrEntry> find(const DWARFSection &S,2322uint64_t Pos) const override {2323auto &Sec = static_cast<const DWARFSectionMap &>(S);2324RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos);2325if (AI == Sec.Relocs.end())2326return std::nullopt;2327return AI->second;2328}23292330const object::ObjectFile *getFile() const override { return Obj; }23312332ArrayRef<SectionName> getSectionNames() const override {2333return SectionNames;2334}23352336bool isLittleEndian() const override { return IsLittleEndian; }2337StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; }2338const DWARFSection &getLineDWOSection() const override {2339return LineDWOSection;2340}2341const DWARFSection &getLocDWOSection() const override {2342return LocDWOSection;2343}2344StringRef getStrDWOSection() const override { return StrDWOSection; }2345const DWARFSection &getStrOffsetsDWOSection() const override {2346return StrOffsetsDWOSection;2347}2348const DWARFSection &getRangesDWOSection() const override {2349return RangesDWOSection;2350}2351const DWARFSection &getRnglistsDWOSection() const override {2352return RnglistsDWOSection;2353}2354const DWARFSection &getLoclistsDWOSection() const override {2355return LoclistsDWOSection;2356}2357const DWARFSection &getAddrSection() const override { return AddrSection; }2358StringRef getCUIndexSection() const override { return CUIndexSection; }2359StringRef getGdbIndexSection() const override { return GdbIndexSection; }2360StringRef getTUIndexSection() const override { return TUIndexSection; }23612362// DWARF v52363const DWARFSection &getStrOffsetsSection() const override {2364return StrOffsetsSection;2365}2366StringRef getLineStrSection() const override { return LineStrSection; }23672368// Sections for DWARF5 split dwarf proposal.2369void forEachInfoDWOSections(2370function_ref<void(const DWARFSection &)> F) const override {2371for (auto &P : InfoDWOSections)2372F(P.second);2373}2374void forEachTypesDWOSections(2375function_ref<void(const DWARFSection &)> F) const override {2376for (auto &P : TypesDWOSections)2377F(P.second);2378}23792380StringRef getAbbrevSection() const override { return AbbrevSection; }2381const DWARFSection &getLocSection() const override { return LocSection; }2382const DWARFSection &getLoclistsSection() const override { return LoclistsSection; }2383StringRef getArangesSection() const override { return ArangesSection; }2384const DWARFSection &getFrameSection() const override {2385return FrameSection;2386}2387const DWARFSection &getEHFrameSection() const override {2388return EHFrameSection;2389}2390const DWARFSection &getLineSection() const override { return LineSection; }2391StringRef getStrSection() const override { return StrSection; }2392const DWARFSection &getRangesSection() const override { return RangesSection; }2393const DWARFSection &getRnglistsSection() const override {2394return RnglistsSection;2395}2396const DWARFSection &getMacroSection() const override { return MacroSection; }2397StringRef getMacroDWOSection() const override { return MacroDWOSection; }2398StringRef getMacinfoSection() const override { return MacinfoSection; }2399StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }2400const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }2401const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }2402const DWARFSection &getGnuPubnamesSection() const override {2403return GnuPubnamesSection;2404}2405const DWARFSection &getGnuPubtypesSection() const override {2406return GnuPubtypesSection;2407}2408const DWARFSection &getAppleNamesSection() const override {2409return AppleNamesSection;2410}2411const DWARFSection &getAppleTypesSection() const override {2412return AppleTypesSection;2413}2414const DWARFSection &getAppleNamespacesSection() const override {2415return AppleNamespacesSection;2416}2417const DWARFSection &getAppleObjCSection() const override {2418return AppleObjCSection;2419}2420const DWARFSection &getNamesSection() const override {2421return NamesSection;2422}24232424StringRef getFileName() const override { return FileName; }2425uint8_t getAddressSize() const override { return AddressSize; }2426void forEachInfoSections(2427function_ref<void(const DWARFSection &)> F) const override {2428for (auto &P : InfoSections)2429F(P.second);2430}2431void forEachTypesSections(2432function_ref<void(const DWARFSection &)> F) const override {2433for (auto &P : TypesSections)2434F(P.second);2435}2436};2437} // namespace24382439std::unique_ptr<DWARFContext>2440DWARFContext::create(const object::ObjectFile &Obj,2441ProcessDebugRelocations RelocAction,2442const LoadedObjectInfo *L, std::string DWPName,2443std::function<void(Error)> RecoverableErrorHandler,2444std::function<void(Error)> WarningHandler,2445bool ThreadSafe) {2446auto DObj = std::make_unique<DWARFObjInMemory>(2447Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction);2448return std::make_unique<DWARFContext>(std::move(DObj),2449std::move(DWPName),2450RecoverableErrorHandler,2451WarningHandler,2452ThreadSafe);2453}24542455std::unique_ptr<DWARFContext>2456DWARFContext::create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,2457uint8_t AddrSize, bool isLittleEndian,2458std::function<void(Error)> RecoverableErrorHandler,2459std::function<void(Error)> WarningHandler,2460bool ThreadSafe) {2461auto DObj =2462std::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);2463return std::make_unique<DWARFContext>(2464std::move(DObj), "", RecoverableErrorHandler, WarningHandler, ThreadSafe);2465}24662467uint8_t DWARFContext::getCUAddrSize() {2468// In theory, different compile units may have different address byte2469// sizes, but for simplicity we just use the address byte size of the2470// first compile unit. In practice the address size field is repeated across2471// various DWARF headers (at least in version 5) to make it easier to dump2472// them independently, not to enable varying the address size.2473auto CUs = compile_units();2474return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize();2475}247624772478