diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index d06818eca9d3..c79d98e34f6e 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -11,6 +11,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include @@ -42,6 +43,7 @@ public: /// Dump this list on OS. void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const; }; @@ -58,7 +60,7 @@ private: public: /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional Offset) const; /// Parse the debug_loc section accessible via the 'data' parameter using the @@ -76,9 +78,13 @@ class DWARFDebugLoclists { public: struct Entry { uint8_t Kind; + uint64_t Offset; uint64_t Value0; uint64_t Value1; SmallVector Loc; + void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const; }; struct LocationList { @@ -86,7 +92,7 @@ public: SmallVector Entries; void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *RegInfo, - DWARFUnit *U, unsigned Indent) const; + DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const; }; private: @@ -101,7 +107,7 @@ private: public: void parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version); void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, - Optional Offset) const; + DIDumpOptions DumpOpts, Optional Offset) const; /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index ed6c2b93ce6b..8cb665967dd3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -305,7 +305,7 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFDebugLoclists Loclists; uint64_t EndOffset = Header.length() + Header.getHeaderOffset(); Loclists.parse(LocData, Offset, EndOffset, Header.getVersion()); - Loclists.dump(OS, 0, MRI, DumpOffset); + Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset); Offset = EndOffset; } } @@ -382,7 +382,7 @@ void DWARFContext::dump( if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo(), *Off); + getDebugLoc()->dump(OS, getRegisterInfo(), DumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, @@ -394,7 +394,7 @@ void DWARFContext::dump( if (const auto *Off = shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, DObj->getLocDWOSection().Data)) { - getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), *Off); + getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOpts, *Off); } if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index bdafafc7a37d..9dd7d974ec05 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/Bitcode/BitcodeAnalyzer.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" @@ -39,6 +40,7 @@ void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const { for (const Entry &E : Entries) { OS << '\n'; @@ -62,12 +64,12 @@ DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, +void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, Optional Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8" PRIx64 ": ", L.Offset); - L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, 12); - OS << "\n\n"; + L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, 12); + OS << "\n"; }; if (Offset) { @@ -78,6 +80,8 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, for (const LocationList &L : Locations) { DumpLocationList(L); + if (&L != &Locations.back()) + OS << '\n'; } } @@ -146,7 +150,11 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data, while (auto Kind = Data.getU8(C)) { Entry E; E.Kind = Kind; + E.Offset = C.tell() - 1; switch (Kind) { + case dwarf::DW_LLE_base_addressx: + E.Value0 = Data.getULEB128(C); + break; case dwarf::DW_LLE_startx_length: E.Value0 = Data.getULEB128(C); // Pre-DWARF 5 has different interpretation of the length field. We have @@ -173,7 +181,8 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data, "LLE of kind %x not supported", (int)Kind); } - if (Kind != dwarf::DW_LLE_base_address) { + if (Kind != dwarf::DW_LLE_base_address && + Kind != dwarf::DW_LLE_base_addressx) { unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C); // A single location description describing the location of the object... Data.getU8(C, E.Loc, Bytes); @@ -183,6 +192,10 @@ DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data, } if (Error Err = C.takeError()) return std::move(Err); + Entry E; + E.Kind = dwarf::DW_LLE_end_of_list; + E.Offset = C.tell() - 1; + LL.Entries.push_back(E); *Offset = C.tell(); return LL; } @@ -210,51 +223,106 @@ DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } +void DWARFDebugLoclists::Entry::dump(raw_ostream &OS, uint64_t &BaseAddr, + bool IsLittleEndian, unsigned AddressSize, + const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent, + size_t MaxEncodingStringLength) const { + if (DumpOpts.Verbose) { + OS << "\n"; + OS.indent(Indent); + auto EncodingString = dwarf::LocListEncodingString(Kind); + // Unsupported encodings should have been reported during parsing. + assert(!EncodingString.empty() && "Unknown loclist entry encoding"); + OS << format("%s%*c", EncodingString.data(), + MaxEncodingStringLength - EncodingString.size() + 1, '('); + switch (Kind) { + case dwarf::DW_LLE_startx_length: + case dwarf::DW_LLE_start_length: + case dwarf::DW_LLE_offset_pair: + OS << format("0x%*.*" PRIx64 ", 0x%*.*" PRIx64, AddressSize * 2, + AddressSize * 2, Value0, AddressSize * 2, AddressSize * 2, + Value1); + break; + case dwarf::DW_LLE_base_addressx: + case dwarf::DW_LLE_base_address: + OS << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2, + Value0); + break; + case dwarf::DW_LLE_end_of_list: + break; + } + OS << ')'; + } + auto PrintPrefix = [&] { + OS << "\n"; + OS.indent(Indent); + if (DumpOpts.Verbose) + OS << format("%*s", MaxEncodingStringLength, (const char *)"=> "); + }; + switch (Kind) { + case dwarf::DW_LLE_startx_length: + PrintPrefix(); + OS << "Addr idx " << Value0 << " (w/ length " << Value1 << "): "; + break; + case dwarf::DW_LLE_start_length: + PrintPrefix(); + DWARFAddressRange(Value0, Value0 + Value1) + .dump(OS, AddressSize, DumpOpts); + OS << ": "; + break; + case dwarf::DW_LLE_offset_pair: + PrintPrefix(); + DWARFAddressRange(BaseAddr + Value0, BaseAddr + Value1) + .dump(OS, AddressSize, DumpOpts); + OS << ": "; + break; + case dwarf::DW_LLE_base_addressx: + if (!DumpOpts.Verbose) + return; + break; + case dwarf::DW_LLE_end_of_list: + if (!DumpOpts.Verbose) + return; + break; + case dwarf::DW_LLE_base_address: + BaseAddr = Value0; + if (!DumpOpts.Verbose) + return; + break; + default: + llvm_unreachable("unreachable locations list kind"); + } + + dumpExpression(OS, Loc, IsLittleEndian, AddressSize, MRI, U); +} void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const { - for (const Entry &E : Entries) { - switch (E.Kind) { - case dwarf::DW_LLE_startx_length: - OS << '\n'; - OS.indent(Indent); - OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): "; - break; - case dwarf::DW_LLE_start_length: - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, - AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2, - E.Value0 + E.Value1); - break; - case dwarf::DW_LLE_offset_pair: - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, - AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2, - AddressSize * 2, BaseAddr + E.Value1); - break; - case dwarf::DW_LLE_base_address: - BaseAddr = E.Value0; - break; - default: - llvm_unreachable("unreachable locations list kind"); - } + size_t MaxEncodingStringLength = 0; + if (DumpOpts.Verbose) + for (const auto &Entry : Entries) + MaxEncodingStringLength = + std::max(MaxEncodingStringLength, + dwarf::LocListEncodingString(Entry.Kind).size()); - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); - } + for (const Entry &E : Entries) + E.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, U, DumpOpts, Indent, + MaxEncodingStringLength); } void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, - const MCRegisterInfo *MRI, + const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, Optional Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8" PRIx64 ": ", L.Offset); - L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, /*Indent=*/12); - OS << "\n\n"; + L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, + /*Indent=*/12); + OS << "\n"; }; if (Offset) { @@ -265,5 +333,7 @@ void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, for (const LocationList &L : Locations) { DumpLocationList(L); + if (&L != &Locations.back()) + OS << '\n'; } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index c1b5dfdb61c7..cec194e8b6b3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -97,8 +97,10 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, uint64_t BaseAddr = 0; if (Optional BA = U->getBaseAddress()) BaseAddr = BA->Address; + auto LLDumpOpts = DumpOpts; + LLDumpOpts.Verbose = false; ExpectedLL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), - MRI, U, Indent); + MRI, U, LLDumpOpts, Indent); } else { OS << '\n'; OS.indent(Indent); diff --git a/llvm/test/CodeGen/X86/debug-loclists.ll b/llvm/test/CodeGen/X86/debug-loclists.ll index 30cab3b01e19..e111d12625c7 100644 --- a/llvm/test/CodeGen/X86/debug-loclists.ll +++ b/llvm/test/CodeGen/X86/debug-loclists.ll @@ -13,8 +13,10 @@ ; CHECK: .debug_loclists contents: ; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000015, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 ; CHECK-NEXT: 0x0000000c: -; CHECK-NEXT: [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0 -; CHECK-NEXT: [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0 +; CHECK-NEXT: DW_LLE_offset_pair(0x0000000000000000, 0x0000000000000004) +; CHECK-NEXT: => [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0 +; CHECK-NEXT: DW_LLE_offset_pair(0x0000000000000004, 0x0000000000000012) +; CHECK-NEXT: => [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0 ; There is no way to use llvm-dwarfdump atm (2018, october) to verify the DW_LLE_* codes emited, ; because dumper is not yet implements that. Use asm code to do this check instead. diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test b/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test index 41893d32690a..783d4b84fbf5 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test +++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test @@ -11,9 +11,14 @@ # CHECK: .debug_loclists contents: # CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 # CHECK-NEXT: 0x0000000c: -# CHECK-NEXT: [0x0000000000000000, 0x0000000000000010): DW_OP_breg5 RDI+0 -# CHECK-NEXT: [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref -# CHECK-NEXT: [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0 +# CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000000, 0x0000000000000010) +# CHECK-NEXT: => [0x0000000000000000, 0x0000000000000010): DW_OP_breg5 RDI+0 +# CHECK-NEXT: DW_LLE_base_address(0x0000000000000500) +# CHECK-NEXT: DW_LLE_offset_pair (0x0000000000000030, 0x0000000000000040) +# CHECK-NEXT: => [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref +# CHECK-NEXT: DW_LLE_start_length(0x0000000000000700, 0x0000000000000010) +# CHECK-NEXT: => [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0 +# CHECK-NEXT: DW_LLE_end_of_list () .section .debug_str,"MS",@progbits,1 .asciz "stub" diff --git a/llvm/test/DebugInfo/X86/fission-ranges.ll b/llvm/test/DebugInfo/X86/fission-ranges.ll index c2b355b994c4..3f9e447f6302 100644 --- a/llvm/test/DebugInfo/X86/fission-ranges.ll +++ b/llvm/test/DebugInfo/X86/fission-ranges.ll @@ -45,18 +45,31 @@ ; if they've changed due to a bugfix, change in register allocation, etc. ; CHECK: [[A]]: -; CHECK-NEXT: Addr idx 2 (w/ length 15): DW_OP_consts +0, DW_OP_stack_value -; CHECK-NEXT: Addr idx 3 (w/ length 15): DW_OP_reg0 RAX -; CHECK-NEXT: Addr idx 4 (w/ length 18): DW_OP_breg7 RSP-8 +; CHECK-NEXT: DW_LLE_startx_length(0x00000002, 0x0000000f) +; CHECK-NEXT: => Addr idx 2 (w/ length 15): DW_OP_consts +0, DW_OP_stack_value +; CHECK-NEXT: DW_LLE_startx_length(0x00000003, 0x0000000f) +; CHECK-NEXT: => Addr idx 3 (w/ length 15): DW_OP_reg0 RAX +; CHECK-NEXT: DW_LLE_startx_length(0x00000004, 0x00000012) +; CHECK-NEXT: => Addr idx 4 (w/ length 18): DW_OP_breg7 RSP-8 +; CHECK-NEXT: DW_LLE_end_of_list () ; CHECK: [[E]]: -; CHECK-NEXT: Addr idx 5 (w/ length 9): DW_OP_reg0 RAX -; CHECK-NEXT: Addr idx 6 (w/ length 98): DW_OP_breg7 RSP-44 +; CHECK-NEXT: DW_LLE_startx_length(0x00000005, 0x00000009) +; CHECK-NEXT: => Addr idx 5 (w/ length 9): DW_OP_reg0 RAX +; CHECK-NEXT: DW_LLE_startx_length(0x00000006, 0x00000062) +; CHECK-NEXT: => Addr idx 6 (w/ length 98): DW_OP_breg7 RSP-44 +; CHECK-NEXT: DW_LLE_end_of_list () ; CHECK: [[B]]: -; CHECK-NEXT: Addr idx 7 (w/ length 15): DW_OP_reg0 RAX -; CHECK-NEXT: Addr idx 8 (w/ length 66): DW_OP_breg7 RSP-32 +; CHECK-NEXT: DW_LLE_startx_length(0x00000007, 0x0000000f) +; CHECK-NEXT: => Addr idx 7 (w/ length 15): DW_OP_reg0 RAX +; CHECK-NEXT: DW_LLE_startx_length(0x00000008, 0x00000042) +; CHECK-NEXT: => Addr idx 8 (w/ length 66): DW_OP_breg7 RSP-32 +; CHECK-NEXT: DW_LLE_end_of_list () ; CHECK: [[D]]: -; CHECK-NEXT: Addr idx 9 (w/ length 15): DW_OP_reg0 RAX -; CHECK-NEXT: Addr idx 10 (w/ length 42): DW_OP_breg7 RSP-20 +; CHECK-NEXT: DW_LLE_startx_length(0x00000009, 0x0000000f) +; CHECK-NEXT: => Addr idx 9 (w/ length 15): DW_OP_reg0 RAX +; CHECK-NEXT: DW_LLE_startx_length(0x0000000a, 0x0000002a) +; CHECK-NEXT: => Addr idx 10 (w/ length 42): DW_OP_breg7 RSP-20 +; CHECK-NEXT: DW_LLE_end_of_list () ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo) ; HDR-NOT: .rela.{{.*}}.dwo diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s index 508d95665463..75fd43f60565 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s @@ -8,7 +8,9 @@ # CHECK: .debug_loclists contents: # CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 # CHECK-NEXT: 0x0000000c: -# CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI +# CHECK-NEXT: DW_LLE_startx_length(0x0000000000000001, 0x0000000000000010) +# CHECK-NEXT: => Addr idx 1 (w/ length 16): DW_OP_reg5 RDI +# CHECK-NEXT: DW_LLE_end_of_list () .section .debug_loclists,"",@progbits .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0