diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -105,16 +105,17 @@ bool IsLittleEndian; public: - void parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version); + void parse(const DWARFDataExtractor &data, uint64_t Offset, + uint64_t EndOffset, uint16_t Version); void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional Offset) const; /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - static Expected parseOneLocationList(const DataExtractor &Data, - uint64_t *Offset, - unsigned Version); + static Expected + parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset, + unsigned Version); }; } // end namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -299,12 +299,11 @@ } 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()); + Data.setAddressSize(Header.getAddrSize()); + Loclists.parse(Data, Offset, EndOffset, Header.getVersion()); Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset); Offset = EndOffset; } @@ -733,7 +732,8 @@ // 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); + DWARFDataExtractor LocData(*DObj, DObj->getLocDWOSection(), 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). diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -140,7 +140,7 @@ } Expected -DWARFDebugLoclists::parseOneLocationList(const DataExtractor &Data, +DWARFDebugLoclists::parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset, unsigned Version) { LocationList LL; LL.Offset = *Offset; @@ -165,7 +165,7 @@ E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_start_length: - E.Value0 = Data.getAddress(C); + E.Value0 = Data.getRelocatedAddress(C); E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_offset_pair: @@ -173,7 +173,7 @@ E.Value1 = Data.getULEB128(C); break; case dwarf::DW_LLE_base_address: - E.Value0 = Data.getAddress(C); + E.Value0 = Data.getRelocatedAddress(C); break; default: cantFail(C.takeError()); @@ -200,7 +200,8 @@ return LL; } -void DWARFDebugLoclists::parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version) { +void DWARFDebugLoclists::parse(const DWARFDataExtractor &data, uint64_t Offset, + uint64_t EndOffset, uint16_t Version) { IsLittleEndian = data.isLittleEndian(); AddressSize = data.getAddressSize(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -119,13 +119,15 @@ } bool UseLocLists = !U->isDWOUnit(); - StringRef LoclistsSectionData = - UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); - - if (!LoclistsSectionData.empty()) { - DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), - Obj.getAddressSize()); - + auto Data = [&] { + if (UseLocLists) + return DWARFDataExtractor(Obj, Obj.getLoclistsSection(), + Ctx.isLittleEndian(), Obj.getAddressSize()); + return DWARFDataExtractor(U->getLocSectionData(), Ctx.isLittleEndian(), + Obj.getAddressSize()); + }(); + + if (!Data.getData().empty()) { // 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 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists.s @@ -0,0 +1,120 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t +# RUN: llvm-dwarfdump %t | FileCheck %s + + +# CHECK: DW_AT_location (0x0000000c +# CHECK-NEXT: Addr idx 0 (w/ length 1): DW_OP_reg0 RAX +# CHECK-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX +# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX +# CHECK-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX +# CHECK-NEXT: Addr idx 57005 (w/ length 1): DW_OP_reg4 RSI) + + + .text +f: # @f +.Lf0: + nop +.Lf1: + nop +.Lf2: + nop +.Lf3: + nop +.Lf4: +.Lfend: + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length +.Ldebug_loclist_table_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 0 # Offset entry count +.Lloclists_table_base0: +.Ldebug_loc0: + .byte 3 # DW_LLE_startx_length + .uleb128 0 # start idx + .uleb128 .Lf1-.Lf0 # length + .byte 1 # Loc expr size + .byte 80 # super-register DW_OP_reg0 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lf1-.Lf0 # starting offset + .uleb128 .Lf2-.Lf0 # ending offset + .byte 1 # Loc expr size + .byte 81 # super-register DW_OP_reg1 + .byte 8 # DW_LLE_start_length + .quad .Lf2 # starting offset + .uleb128 .Lf3-.Lf2 # length + .byte 1 # Loc expr size + .byte 82 # super-register DW_OP_reg2 + .byte 6 # DW_LLE_base_address + .quad .Lf3 # base address + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lf3-.Lf3 # starting offset + .uleb128 .Lf4-.Lf3 # ending offset + .byte 1 # Loc expr size + .byte 83 # super-register DW_OP_reg3 + .byte 3 # DW_LLE_startx_length + .uleb128 0xdead # start idx + .uleb128 .Lf1-.Lf0 # length + .byte 1 # Loc expr size + .byte 84 # super-register DW_OP_reg4 + .byte 0 # DW_LLE_end_of_list +.Ldebug_loclist_table_end0: + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x3c DW_TAG_compile_unit + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x1c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfend-.Lf0 # DW_AT_high_pc + .byte 3 # Abbrev [3] 0x36:0xc DW_TAG_formal_parameter + .long .Ldebug_loc0 # DW_AT_location + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lf0 +.Ldebug_addr_end0: