Index: include/llvm/BinaryFormat/Dwarf.h
===================================================================
--- include/llvm/BinaryFormat/Dwarf.h
+++ include/llvm/BinaryFormat/Dwarf.h
@@ -428,6 +428,7 @@
 StringRef AtomTypeString(unsigned Atom);
 StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind);
 StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
+StringRef LocationListEntryString(unsigned Entry);
 StringRef IndexString(unsigned Idx);
 /// @}
 
Index: include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
===================================================================
--- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -20,6 +20,17 @@
 class MCRegisterInfo;
 class raw_ostream;
 
+class IsBaseAddressError : public ErrorInfo<IsBaseAddressError> {
+public:
+  static char ID;
+
+  void log(raw_ostream &OS) const override { OS << "Is base address"; }
+
+  std::error_code convertToErrorCode() const override {
+    return inconvertibleErrorCode();
+  }
+};
+
 class DWARFDebugLoc {
 public:
   /// A single location within a location list.
@@ -79,6 +90,22 @@
     uint64_t Value0;
     uint64_t Value1;
     SmallVector<uint8_t, 4> Loc;
+
+    /// Return the half-open range of addresses covered by this entry.
+    /// DW_LLE_offset_pair entries are resolved using the given base address,
+    /// and the supplied DWARFUnit is used to look up any pooled (debug_addr)
+    /// addresses. In case of failure, an error is returned. If we could not get
+    /// an address range because this is a base address selection entry
+    /// (DW_LLE_base_address), then the error is of type IsBaseAddressError, and
+    /// the BaseAddr argument is updated accordingly.
+    Expected<std::pair<uint64_t, uint64_t>> getRange(DWARFUnit *U,
+                                                     uint64_t &BaseAddr) const;
+
+    /// Same as above, but uses a callback to resolve any address pool
+    /// references.
+    Expected<std::pair<uint64_t, uint64_t>>
+    getRange(function_ref<Optional<uint64_t>(uint32_t)> AddrOffsetResolver,
+             uint64_t &BaseAddr) const;
   };
 
   struct LocationList {
Index: lib/BinaryFormat/Dwarf.cpp
===================================================================
--- lib/BinaryFormat/Dwarf.cpp
+++ lib/BinaryFormat/Dwarf.cpp
@@ -617,6 +617,31 @@
   return StringRef();
 }
 
+StringRef llvm::dwarf::LocationListEntryString(unsigned Entry) {
+  switch(Entry) {
+  default:
+    return StringRef();
+  case DW_LLE_end_of_list:
+    return "DW_LLE_end_of_list";
+  case DW_LLE_base_addressx:
+    return "DW_LLE_base_addressx";
+  case DW_LLE_startx_endx:
+    return "DW_LLE_startx_endx";
+  case DW_LLE_startx_length:
+    return "DW_LLE_startx_length";
+  case DW_LLE_offset_pair:
+    return "DW_LLE_offset_pair";
+  case DW_LLE_default_location:
+    return "DW_LLE_default_location";
+  case DW_LLE_base_address:
+    return "DW_LLE_base_address";
+  case DW_LLE_start_end:
+    return "DW_LLE_start_end";
+  case DW_LLE_start_length:
+    return "DW_LLE_start_length";
+  }
+}
+
 StringRef llvm::dwarf::IndexString(unsigned Idx) {
   switch (Idx) {
   default:
Index: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
===================================================================
--- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -23,6 +23,8 @@
 
 using namespace llvm;
 
+char IsBaseAddressError::ID;
+
 // When directly dumping the .debug_loc without a compile unit, we have to guess
 // at the DWARF version. This only affects DW_OP_call_ref, which is a rare
 // expression that LLVM doesn't produce. Guessing the wrong version means we
@@ -153,6 +155,7 @@
         E.Value1 = Data.getULEB128(C);
       break;
     case dwarf::DW_LLE_start_length:
+      // TODO: Read this as a relocated address.
       E.Value0 = Data.getAddress(C);
       E.Value1 = Data.getULEB128(C);
       break;
@@ -207,6 +210,43 @@
   return nullptr;
 }
 
+Expected<std::pair<uint64_t, uint64_t>> DWARFDebugLoclists::Entry::getRange(
+    function_ref<Optional<uint64_t>(uint32_t)> AddrOffsetResolver,
+    uint64_t &BaseAddr) const {
+  switch (Kind) {
+  case dwarf::DW_LLE_startx_length:
+    if (Optional<uint64_t> Start = AddrOffsetResolver(Value0))
+      return std::make_pair(*Start, *Start + Value1);
+    else
+      return createStringError(inconvertibleErrorCode(),
+                               "Reading debug_addr failed");
+
+  case dwarf::DW_LLE_start_length:
+    return std::make_pair(Value0, Value0 + Value1);
+  case dwarf::DW_LLE_offset_pair:
+    return std::make_pair(BaseAddr + Value0, BaseAddr + Value1);
+  case dwarf::DW_LLE_base_address:
+    BaseAddr = Value0;
+    return make_error<IsBaseAddressError>();
+  default:
+    llvm_unreachable("Unsupported locations list kind");
+  }
+}
+
+Expected<std::pair<uint64_t, uint64_t>>
+DWARFDebugLoclists::Entry::getRange(DWARFUnit *U, uint64_t &BaseAddr) const {
+  return getRange(
+      [U](uint32_t Index) -> Optional<uint64_t> {
+        if (!U)
+          return llvm::None;
+        if (Optional<object::SectionedAddress> Addr =
+                U->getAddrOffsetSectionItem(Index))
+          return Addr->Address;
+        return llvm::None;
+      },
+      BaseAddr);
+}
+
 void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
                                             bool IsLittleEndian,
                                             unsigned AddressSize,
@@ -214,32 +254,24 @@
                                             DWARFUnit *U,
                                             unsigned Indent) const {
   for (const Entry &E : Entries) {
-    switch (E.Kind) {
-    case dwarf::DW_LLE_startx_length:
+    if (Expected<std::pair<uint64_t, uint64_t>> Range =
+            E.getRange(U, BaseAddr)) {
       OS << '\n';
       OS.indent(Indent);
-      OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): ";
-      break;
-    case dwarf::DW_LLE_start_length:
+      OS << format("[0x%.*" PRIx64 ", 0x%.*" PRIx64 ")", AddressSize * 2,
+                   Range->first, AddressSize * 2, Range->second);
+    } else {
+      bool IsBaseAddress = Range.errorIsA<IsBaseAddressError>();
+      consumeError(Range.takeError());
+      if (IsBaseAddress)
+        continue;
       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");
+      OS << "{" << dwarf::LocationListEntryString(E.Kind)
+         << format(", 0x%.*" PRIx64 ", 0x%.*" PRIx64 "}", AddressSize * 2,
+                   E.Value0, AddressSize * 2, E.Value1);
     }
+    OS << ": ";
 
     dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
   }
Index: test/DebugInfo/X86/fission-ranges.ll
===================================================================
--- test/DebugInfo/X86/fission-ranges.ll
+++ test/DebugInfo/X86/fission-ranges.ll
@@ -45,18 +45,19 @@
 ; 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}: DW_OP_consts +0, DW_OP_stack_value
+; CHECK-NEXT:   {DW_LLE_startx_length, 0x00000003, 0x0000000f}: DW_OP_reg0 RAX
+; CHECK-NEXT:   {DW_LLE_startx_length, 0x00000004, 0x00000012}: DW_OP_breg7 RSP-8
 ; 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}: DW_OP_reg0 RAX
+; CHECK-NEXT:   {DW_LLE_startx_length, 0x00000006, 0x00000062}: DW_OP_breg7 RSP-44
+
 ; 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}: DW_OP_reg0 RAX
+; CHECK-NEXT:   {DW_LLE_startx_length, 0x00000008, 0x00000042}: DW_OP_breg7 RSP-32
 ; 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}: DW_OP_reg0 RAX
+; CHECK-NEXT:   {DW_LLE_startx_length, 0x0000000a, 0x0000002a}: DW_OP_breg7 RSP-20
 
 ; Make sure we don't produce any relocations in any .dwo section (though in particular, debug_info.dwo)
 ; HDR-NOT: .rela.{{.*}}.dwo
Index: test/DebugInfo/X86/loclists-dwp.ll
===================================================================
--- test/DebugInfo/X86/loclists-dwp.ll
+++ test/DebugInfo/X86/loclists-dwp.ll
@@ -19,10 +19,10 @@
 ; void b(int i) { asm("" : : : "rdi"); }
 
 ; CHECK:      DW_AT_location [DW_FORM_sec_offset]   (0x00000000
-; CHECK-NEXT: Addr idx 0 (w/ length 6): DW_OP_reg5 RDI)
+; CHECK-NEXT: {DW_LLE_startx_length, 0x0000000000000000, 0x0000000000000006}: DW_OP_reg5 RDI)
 
 ; CHECK:      DW_AT_location [DW_FORM_sec_offset]   (0x00000000
-; CHECK-NEXT: Addr idx 0 (w/ length 0): DW_OP_reg5 RDI)
+; CHECK-NEXT: {DW_LLE_startx_length, 0x0000000000000000, 0x0000000000000000}: DW_OP_reg5 RDI)
 
 target triple = "x86_64-unknown-linux-gnu"
 
Index: test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
===================================================================
--- test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
+++ test/tools/llvm-dwarfdump/X86/debug_loc_dwo.s
@@ -6,7 +6,7 @@
 
 # CHECK:         .debug_loc.dwo contents:
 # CHECK-NEXT:    0x00000000:
-# CHECK-NEXT:    Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT:    {DW_LLE_startx_length, 0x00000001, 0x00000010}: DW_OP_reg5 RDI
 
 .section .debug_loc.dwo,"",@progbits
 # One location list. The pre-DWARF v5 implementation only recognizes
Index: test/tools/llvm-dwarfdump/X86/debug_loclists.s
===================================================================
--- /dev/null
+++ test/tools/llvm-dwarfdump/X86/debug_loclists.s
@@ -0,0 +1,122 @@
+# 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:        [0x0000000000000000, 0x0000000000000001): 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:        {DW_LLE_startx_length, 0x000000000000dead, 0x0000000000000001}: 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
+        # TODO: Make it possible to use .Lf2 here.
+        .quad   2                       #   starting offset
+        .uleb128 .Lf3-.Lf2              #   length
+        .byte   1                       # Loc expr size
+        .byte   82                      # super-register DW_OP_reg2
+        .byte   6                       # DW_LLE_base_address
+        # TODO: Make it possible to use .Lf3 here.
+        .quad   3                       #   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:
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
@@ -8,7 +8,7 @@
 # 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:    0x00000000:
-# CHECK-NEXT:    Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
+# CHECK-NEXT:    {DW_LLE_startx_length, 0x0000000000000001, 0x0000000000000010}: DW_OP_reg5 RDI
 
 .section .debug_loclists,"",@progbits
  .long  .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0