diff options
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFContext.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 154 |
1 files changed, 115 insertions, 39 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index c06d85d50609..aaa6d5250f23 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -288,6 +288,7 @@ static void dumpRnglistsSection( static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDataExtractor Data, const MCRegisterInfo *MRI, + const DWARFObject &Obj, Optional<uint64_t> DumpOffset) { uint64_t Offset = 0; @@ -299,13 +300,21 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, } Header.dump(OS, DumpOpts); - DataExtractor LocData(Data.getData(), - Data.isLittleEndian(), Header.getAddrSize()); - DWARFDebugLoclists Loclists; uint64_t EndOffset = Header.length() + Header.getHeaderOffset(); - Loclists.parse(LocData, Offset, EndOffset, Header.getVersion()); - Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset); + Data.setAddressSize(Header.getAddrSize()); + DWARFDebugLoclists Loc(Data, Header.getVersion()); + if (DumpOffset) { + if (DumpOffset >= Offset && DumpOffset < EndOffset) { + Offset = *DumpOffset; + Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, nullptr, + DumpOpts, /*Indent=*/0); + OS << "\n"; + return; + } + } else { + Loc.dumpRange(Offset, EndOffset - Offset, OS, MRI, Obj, DumpOpts); + } Offset = EndOffset; } } @@ -380,21 +389,45 @@ void DWARFContext::dump( dumpDebugType(".debug_types.dwo", dwo_types_section_units()); } + DIDumpOptions LLDumpOpts = DumpOpts; + if (LLDumpOpts.Verbose) + LLDumpOpts.DisplayRawContents = true; + if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo(), DumpOpts, *Off); + getDebugLoc()->dump(OS, getRegisterInfo(), *DObj, LLDumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, DObj->getLoclistsSection().Data)) { DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), 0); - dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); + } + if (const auto *Off = + shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists, + DObj->getLoclistsDWOSection().Data)) { + DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(), + isLittleEndian(), 0); + dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off); } + if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, DObj->getLocDWOSection().Data)) { - getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOpts, *Off); + DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(), + 4); + DWARFDebugLoclists Loc(Data, /*Version=*/4); + if (*Off) { + uint64_t Offset = **Off; + Loc.dumpLocationList(&Offset, OS, + /*BaseAddr=*/None, getRegisterInfo(), *DObj, nullptr, + LLDumpOpts, /*Indent=*/0); + OS << "\n"; + } else { + Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), *DObj, + LLDumpOpts); + } } if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, @@ -409,6 +442,9 @@ void DWARFContext::dump( if (Explicit || !getDebugMacro()->empty()) { OS << "\n.debug_macinfo contents:\n"; getDebugMacro()->dump(OS); + } else if (ExplicitDWO || !getDebugMacroDWO()->empty()) { + OS << "\n.debug_macinfo.dwo contents:\n"; + getDebugMacroDWO()->dump(OS); } } @@ -715,32 +751,16 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { if (Loc) return Loc.get(); - Loc.reset(new DWARFDebugLoc); // Assume all units have the same address byte size. - if (getNumCompileUnits()) { - DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), - getUnitAtIndex(0)->getAddressByteSize()); - Loc->parse(LocData); - } + auto LocData = + getNumCompileUnits() + ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(), + getUnitAtIndex(0)->getAddressByteSize()) + : DWARFDataExtractor("", isLittleEndian(), 0); + Loc.reset(new DWARFDebugLoc(std::move(LocData))); return Loc.get(); } -const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() { - if (LocDWO) - return LocDWO.get(); - - LocDWO.reset(new DWARFDebugLoclists()); - // Assume all compile units have the same address byte size. - // FIXME: We don't need AddressSize for split DWARF since relocatable - // addresses cannot appear there. At the moment DWARFExpression requires it. - DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4); - // Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and - // that means we are parsing the new style .debug_loc (pre-standatized version - // of the .debug_loclists). - LocDWO->parse(LocData, 0, LocData.getData().size(), 4 /* Version */); - return LocDWO.get(); -} - const DWARFDebugAranges *DWARFContext::getDebugAranges() { if (Aranges) return Aranges.get(); @@ -781,6 +801,17 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() { return DebugFrame.get(); } +const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() { + if (MacroDWO) + return MacroDWO.get(); + + DataExtractor MacinfoDWOData(DObj->getMacinfoDWOSection(), isLittleEndian(), + 0); + MacroDWO.reset(new DWARFDebugMacro()); + MacroDWO->parse(MacinfoDWOData); + return MacroDWO.get(); +} + const DWARFDebugMacro *DWARFContext::getDebugMacro() { if (Macro) return Macro.get(); @@ -843,7 +874,7 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) { } Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( - DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) { + DWARFUnit *U, function_ref<void(Error)> RecoverableErrorCallback) { if (!Line) Line.reset(new DWARFDebugLine); @@ -1027,19 +1058,56 @@ static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { return Optional<uint64_t>(); } +static Optional<int64_t> +getExpressionFrameOffset(ArrayRef<uint8_t> Expr, + Optional<unsigned> FrameBaseReg) { + if (!Expr.empty() && + (Expr[0] == DW_OP_fbreg || + (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) { + unsigned Count; + int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end()); + // A single DW_OP_fbreg or DW_OP_breg. + if (Expr.size() == Count + 1) + return Offset; + // Same + DW_OP_deref (Fortran arrays look like this). + if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref) + return Offset; + // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value) + } + return None; +} + void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, std::vector<DILocal> &Result) { if (Die.getTag() == DW_TAG_variable || Die.getTag() == DW_TAG_formal_parameter) { DILocal Local; - if (auto NameAttr = Subprogram.find(DW_AT_name)) - if (Optional<const char *> Name = NameAttr->getAsCString()) - Local.FunctionName = *Name; - if (auto LocationAttr = Die.find(DW_AT_location)) - if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock()) - if (!Location->empty() && (*Location)[0] == DW_OP_fbreg) - Local.FrameOffset = - decodeSLEB128(Location->data() + 1, nullptr, Location->end()); + if (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName)) + Local.FunctionName = Name; + + Optional<unsigned> FrameBaseReg; + if (auto FrameBase = Subprogram.find(DW_AT_frame_base)) + if (Optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock()) + if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 && + (*Expr)[0] <= DW_OP_reg31) { + FrameBaseReg = (*Expr)[0] - DW_OP_reg0; + } + + if (Expected<std::vector<DWARFLocationExpression>> Loc = + Die.getLocations(DW_AT_location)) { + for (const auto &Entry : *Loc) { + if (Optional<int64_t> FrameOffset = + getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) { + Local.FrameOffset = *FrameOffset; + break; + } + } + } else { + // FIXME: missing DW_AT_location is OK here, but other errors should be + // reported to the user. + consumeError(Loc.takeError()); + } + if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); @@ -1377,6 +1445,7 @@ class DWARFObjInMemory final : public DWARFObject { DWARFSectionMap LocSection; DWARFSectionMap LoclistsSection; + DWARFSectionMap LoclistsDWOSection; DWARFSectionMap LineSection; DWARFSectionMap RangesSection; DWARFSectionMap RnglistsSection; @@ -1403,6 +1472,7 @@ class DWARFObjInMemory final : public DWARFObject { return StringSwitch<DWARFSectionMap *>(Name) .Case("debug_loc", &LocSection) .Case("debug_loclists", &LoclistsSection) + .Case("debug_loclists.dwo", &LoclistsDWOSection) .Case("debug_line", &LineSection) .Case("debug_frame", &FrameSection) .Case("eh_frame", &EHFrameSection) @@ -1431,6 +1501,7 @@ class DWARFObjInMemory final : public DWARFObject { StringRef ArangesSection; StringRef StrSection; StringRef MacinfoSection; + StringRef MacinfoDWOSection; StringRef AbbrevDWOSection; StringRef StrDWOSection; StringRef CUIndexSection; @@ -1450,6 +1521,7 @@ class DWARFObjInMemory final : public DWARFObject { .Case("debug_aranges", &ArangesSection) .Case("debug_str", &StrSection) .Case("debug_macinfo", &MacinfoSection) + .Case("debug_macinfo.dwo", &MacinfoDWOSection) .Case("debug_abbrev.dwo", &AbbrevDWOSection) .Case("debug_str.dwo", &StrDWOSection) .Case("debug_cu_index", &CUIndexSection) @@ -1733,6 +1805,9 @@ public: const DWARFSection &getRnglistsDWOSection() const override { return RnglistsDWOSection; } + const DWARFSection &getLoclistsDWOSection() const override { + return LoclistsDWOSection; + } const DWARFSection &getAddrSection() const override { return AddrSection; } StringRef getCUIndexSection() const override { return CUIndexSection; } StringRef getGdbIndexSection() const override { return GdbIndexSection; } @@ -1773,6 +1848,7 @@ public: return RnglistsSection; } StringRef getMacinfoSection() const override { return MacinfoSection; } + StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; } const DWARFSection &getPubnamesSection() const override { return PubnamesSection; } const DWARFSection &getPubtypesSection() const override { return PubtypesSection; } const DWARFSection &getGnuPubnamesSection() const override { |