diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 16 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 25 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/debug-loclists.ll | 22 |
9 files changed, 86 insertions, 12 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index f7f08b4a499..52a0247b3e4 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -188,6 +188,7 @@ public: /// /// \returns anm optional absolute section offset value for the attribute. Optional<uint64_t> getRangesBaseAttribute() const; + Optional<uint64_t> getLocBaseAttribute() const; /// Get the DW_AT_high_pc attribute value as an address. /// diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index b518900811c..d0a8533d1e3 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -200,6 +200,8 @@ class DWARFUnit { const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; uint64_t RangeSectionBase; + const DWARFSection *LocSection; + uint64_t LocSectionBase; /// Location table of this unit. std::unique_ptr<DWARFLocationTable> LocTable; @@ -219,6 +221,7 @@ class DWARFUnit { /// A table of range lists (DWARF v5 and later). Optional<DWARFDebugRnglistTable> RngListTable; + Optional<DWARFListTableHeader> LoclistTableHeader; mutable const DWARFAbbreviationDeclarationSet *Abbrevs; llvm::Optional<object::SectionedAddress> BaseAddr; @@ -305,6 +308,14 @@ public: RangeSection = RS; RangeSectionBase = Base; } + void setLocSection(const DWARFSection *LS, uint64_t Base) { + LocSection = LS; + LocSectionBase = Base; + } + + uint64_t getLocSectionBase() const { + return LocSectionBase; + } Optional<object::SectionedAddress> getAddrOffsetSectionItem(uint32_t Index) const; @@ -421,6 +432,11 @@ public: return None; } + Optional<uint64_t> getLoclistOffset(uint32_t Index) { + if (LoclistTableHeader) + return LoclistTableHeader->getOffsetEntry(Index); + return None; + } Expected<DWARFAddressRangesVector> collectAddressRanges(); /// Returns subprogram DIE with address range encompassing the provided diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index f4134da48ca..c4d5b717b25 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -798,6 +798,8 @@ void DIEBlock::print(raw_ostream &O) const { //===----------------------------------------------------------------------===// unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_loclistx) + return getULEB128Size(Index); if (Form == dwarf::DW_FORM_data4) return 4; if (Form == dwarf::DW_FORM_sec_offset) @@ -808,6 +810,10 @@ unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { /// EmitValue - Emit label value. /// void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_loclistx) { + AP->EmitULEB128(Index); + return; + } DwarfDebug *DD = AP->getDwarfDebug(); MCSymbol *Label = DD->getDebugLocs().getList(Index).Label; AP->emitDwarfSymbolReference(Label, /*ForceOffset*/ DD->useSplitDwarf()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index a61c98ec1c1..9578e01abdd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1220,8 +1220,11 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, /// Add a Dwarf loclistptr attribute data and value. void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index) { - dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4; + dwarf::Form Form = dwarf::DW_FORM_data4; + if (DD->getDwarfVersion() == 4) + Form =dwarf::DW_FORM_sec_offset; + if (DD->getDwarfVersion() >= 5) + Form =dwarf::DW_FORM_loclistx; Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index)); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c240099910e..d9b5eb1d6d0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2323,9 +2323,12 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, // FIXME: Generate the offsets table and use DW_FORM_loclistx with the // DW_AT_loclists_base attribute. Until then set the number of offsets to 0. Asm->OutStreamer->AddComment("Offset entry count"); - Asm->emitInt32(0); + Asm->emitInt32(DebugLocs.getLists().size()); Asm->OutStreamer->EmitLabel(DebugLocs.getSym()); + for (const auto &List : DebugLocs.getLists()) + Asm->EmitLabelDifference(List.Label, DebugLocs.getSym(), 4); + return TableEnd; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 49a7f7dc2a5..7fa72b1bb57 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -96,6 +96,13 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, uint64_t Offset = *FormValue.getAsSectionOffset(); + if (FormValue.getForm() == DW_FORM_loclistx) { + FormValue.dump(OS, DumpOpts); + if (auto LoclistOffset = U->getLoclistOffset(Offset)) + Offset = *LoclistOffset + U->getLocSectionBase(); + else + return; + } U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI, U, LLDumpOpts, Indent); return; @@ -409,6 +416,10 @@ Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); } +Optional<uint64_t> DWARFDie::getLocBaseAttribute() const { + return toSectionOffset(find(DW_AT_loclists_base)); +} + Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { if (auto FormValue = find(DW_AT_high_pc)) { if (auto Address = FormValue->getAsAddress()) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 26090638b34..820f530a3e3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -312,6 +312,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_udata: case DW_FORM_ref_udata: case DW_FORM_rnglistx: + case DW_FORM_loclistx: Value.uval = Data.getULEB128(OffsetPtr); break; case DW_FORM_string: @@ -551,6 +552,10 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue); break; + case DW_FORM_loclistx: + OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue); + break; + // Should be formatted to 64-bit for DWARF64. case DW_FORM_sec_offset: AddrOS << format("0x%08x", (uint32_t)UValue); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index e5cba5e50b3..2eb7d2f945a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -352,6 +352,7 @@ void DWARFUnit::clear() { Abbrevs = nullptr; BaseAddr.reset(); RangeSectionBase = 0; + LocSectionBase = 0; AddrOffsetSectionBase = 0; clearDIEs(false); DWO.reset(); @@ -442,11 +443,13 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { if (!IsDWO) { assert(AddrOffsetSectionBase == 0); assert(RangeSectionBase == 0); + assert(LocSectionBase == 0); AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0); if (!AddrOffsetSectionBase) AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); + LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0); } // In general, in DWARF v5 and beyond we derive the start of the unit's @@ -498,6 +501,28 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { if (IsDWO && RngListTable) RangeSectionBase = RngListTable->getHeaderSize(); } + + // FIXME: add loclists.dwo support + setLocSection(&Context.getDWARFObj().getLoclistsSection(), + toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0)); + + if (LocSection->Data.size()) { + LoclistTableHeader.emplace(".debug_loclists", "locations"); + uint64_t Offset = LocSectionBase; + uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Header.getFormat()); + DWARFDataExtractor Data(Context.getDWARFObj(), *LocSection, + isLittleEndian, getAddressByteSize()); + if (Offset < HeaderSize) + return createStringError(errc::invalid_argument, + "did not detect a valid" + " list table with base = 0x%" PRIx64 "\n", + Offset); + Offset -= HeaderSize; + if (Error E = LoclistTableHeader->extract(Data, &Offset)) + return createStringError(errc::invalid_argument, + "parsing a loclist table: " + + toString(std::move(E))); + } } // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for diff --git a/llvm/test/CodeGen/X86/debug-loclists.ll b/llvm/test/CodeGen/X86/debug-loclists.ll index ba6eb6a988c..f22e9e1a5c4 100644 --- a/llvm/test/CodeGen/X86/debug-loclists.ll +++ b/llvm/test/CodeGen/X86/debug-loclists.ll @@ -2,32 +2,36 @@ ; RUN: llvm-dwarfdump -v -debug-info -debug-loclists %t | FileCheck %s ; CHECK: DW_TAG_variable -; FIXME: Use DW_FORM_loclistx to reduce relocations -; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x0000000c +; CHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist = 0x00000018: ; CHECK-NEXT: [0x0000000000000000, 0x0000000000000003): DW_OP_consts +3, DW_OP_stack_value ; CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_consts +4, DW_OP_stack_value) ; CHECK-NEXT: DW_AT_name {{.*}} "y" ; CHECK: DW_TAG_variable -; FIXME: Use DW_FORM_loclistx to reduce relocations -; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x0000001d +; CHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x1) loclist = 0x00000029: ; CHECK-NEXT: [0x0000000000000000, 0x0000000000000003): DW_OP_consts +5, DW_OP_stack_value) ; CHECK-NEXT: DW_AT_name {{.*}} "x" ; CHECK: DW_TAG_variable ; FIXME: Use DW_FORM_loclistx to reduce relocations -; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000025 +; CHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x2) loclist = 0x00000031: ; CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX) ; CHECK-NEXT: DW_AT_name {{.*}} "r" ; CHECK: .debug_loclists contents: -; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000029, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000035, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000003 + +; CHECK-NEXT: offsets: [ +; CHECK-NEXT: 0x0000000c => 0x00000018 +; CHECK-NEXT: 0x0000001d => 0x00000029 +; CHECK-NEXT: 0x00000025 => 0x00000031 +; CHECK-NEXT: ] ; Don't use startx_length if there's more than one entry, because the shared ; base address will be useful for both the range that does start at the start of ; the function, and the one that doesn't. -; CHECK-NEXT: 0x0000000c: +; CHECK-NEXT: 0x00000018: ; CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000) ; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000003): DW_OP_consts +3, DW_OP_stack_value ; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004): DW_OP_consts +4, DW_OP_stack_value @@ -35,14 +39,14 @@ ; Show that startx_length can be used when the address range starts at the start of the function. -; CHECK: 0x0000001d: +; CHECK: 0x00000029: ; CHECK-NEXT: DW_LLE_startx_length (0x0000000000000000, 0x0000000000000003): DW_OP_consts +5, DW_OP_stack_value ; CHECK-NEXT: DW_LLE_end_of_list () ; And use a base address when the range doesn't start at an existing/useful ; address in the pool. -; CHECK: 0x00000025: +; CHECK: 0x00000031: ; CHECK-NEXT: DW_LLE_base_addressx (0x0000000000000000) ; CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000003, 0x0000000000000004): DW_OP_reg0 RAX ; CHECK-NEXT: DW_LLE_end_of_list () |