Index: include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -100,15 +100,15 @@ bool IsLittleEndian; public: - void parse(DataExtractor data); + void parse(DataExtractor data, unsigned Version); void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, Optional Offset) const; /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - static Optional parseOneLocationList(DataExtractor Data, - uint32_t *Offset); + static Optional + parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version); }; } // end namespace llvm Index: include/llvm/DebugInfo/DWARF/DWARFListTable.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -99,6 +99,7 @@ uint32_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } uint32_t getLength() const { return HeaderData.Length; } + uint16_t getVersion() const { return HeaderData.Version; } StringRef getSectionName() const { return SectionName; } StringRef getListTypeString() const { return ListTypeString; } dwarf::DwarfFormat getFormat() const { return Format; } Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -309,7 +309,7 @@ DataExtractor LocData(Data.getData().drop_front(Offset), Data.isLittleEndian(), Header.getAddrSize()); - Loclists.parse(LocData); + Loclists.parse(LocData, Header.getVersion()); Loclists.dump(OS, 0, MRI, DumpOffset); } @@ -732,7 +732,10 @@ // 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); - LocDWO->parse(LocData); + // 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, 4 /* Version */); return LocDWO.get(); } Index: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -145,7 +145,8 @@ } Optional -DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset) { +DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset, + unsigned Version) { LocationList LL; LL.Offset = *Offset; @@ -158,7 +159,12 @@ switch (Kind) { case dwarf::DW_LLE_startx_length: E.Value0 = Data.getULEB128(Offset); - E.Value1 = Data.getU32(Offset); + // Pre-DWARF 5 has different interpretation of the length field. We have + // to support both pre- and standartized styles for the compatibility. + if (Version < 5) + E.Value1 = Data.getU32(Offset); + else + E.Value1 = Data.getULEB128(Offset); break; case dwarf::DW_LLE_start_length: E.Value0 = Data.getAddress(Offset); @@ -189,13 +195,13 @@ return LL; } -void DWARFDebugLoclists::parse(DataExtractor data) { +void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) { IsLittleEndian = data.isLittleEndian(); AddressSize = data.getAddressSize(); uint32_t Offset = 0; while (data.isValidOffset(Offset)) { - if (auto LL = parseOneLocationList(data, &Offset)) + if (auto LL = parseOneLocationList(data, &Offset, Version)) Locations.push_back(std::move(*LL)); else return; Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -118,12 +118,20 @@ return; } + bool UseLocLists = !U->isDWOUnit(); StringRef LoclistsSectionData = - U->isDWOUnit() ? U->getLocSectionData() : Obj.getLoclistsSection().Data; + UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); + if (!LoclistsSectionData.empty()) { DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), Obj.getAddressSize()); - auto LL = DWARFDebugLoclists::parseOneLocationList(Data, &Offset); + + // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). + // Modern locations list (.debug_loclists) are used starting from v5. + // Ideally we should take the version from the .debug_loclists section + // header, but using CU's version for simplicity. + auto LL = DWARFDebugLoclists::parseOneLocationList( + Data, &Offset, UseLocLists ? U->getVersion() : 4); uint64_t BaseAddr = 0; if (Optional BA = U->getBaseAddress()) Index: test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s =================================================================== --- test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s +++ test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s @@ -0,0 +1,27 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o +# RUN: llvm-dwarfdump -v %t.o | FileCheck %s + +# DW_LLE_startx_length has different `length` encoding in pre-DWARF 5 +# and final DWARF 5 versions. This test checks we are able to parse +# the final version which uses ULEB128 and not the U32. + +# CHECK: .debug_loclists contents: +# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +# CHECK-NEXT: 0x00000000: +# CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI + +.section .debug_loclists,"",@progbits + .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 +.Ldebug_loclist_table_start0: + .short 5 # Version. + .byte 8 # Address size. + .byte 0 # Segmen selector size. + .long 0 # Offset entry count. + + .byte 3 # DW_LLE_startx_length + .byte 0x01 # Index + .uleb128 0x10 # Length + .short 1 # Loc expr size + .byte 85 # DW_OP_reg5 + .byte 0 # DW_LLE_end_of_list +.Ldebug_loclist_table_end0: