[Lldb-commits] [lldb] 5e9c9b3 - [LLDB][NativePDB] Add support for S_DEFRANGE_REGISTER and S_DEFRANGE_SUBFIELD_REGISTER

Zequan Wu via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 10 12:40:39 PST 2022


Author: Zequan Wu
Date: 2022-03-10T12:40:31-08:00
New Revision: 5e9c9b324a1f7f904b733852d0a05a43e9783cbb

URL: https://github.com/llvm/llvm-project/commit/5e9c9b324a1f7f904b733852d0a05a43e9783cbb
DIFF: https://github.com/llvm/llvm-project/commit/5e9c9b324a1f7f904b733852d0a05a43e9783cbb.diff

LOG: [LLDB][NativePDB] Add support for S_DEFRANGE_REGISTER and S_DEFRANGE_SUBFIELD_REGISTER

Differential Revision: https://reviews.llvm.org/D119508

Added: 
    lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
    lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s

Modified: 
    lldb/include/lldb/Utility/RangeMap.h
    lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/source/Symbol/Variable.cpp
    lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
    lldb/unittests/Utility/RangeMapTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 422f90d807a72..7eb0cab8084c7 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -59,6 +59,17 @@ template <typename B, typename S> struct Range {
     return false;
   }
 
+  Range Intersect(const Range &rhs) const {
+    const BaseType lhs_base = this->GetRangeBase();
+    const BaseType rhs_base = rhs.GetRangeBase();
+    const BaseType lhs_end = this->GetRangeEnd();
+    const BaseType rhs_end = rhs.GetRangeEnd();
+    Range range;
+    range.SetRangeBase(std::max(lhs_base, rhs_base));
+    range.SetRangeEnd(std::min(lhs_end, rhs_end));
+    return range;
+  }
+
   BaseType GetRangeEnd() const { return base + size; }
 
   void SetRangeEnd(BaseType end) {
@@ -99,12 +110,7 @@ template <typename B, typename S> struct Range {
 
   // Returns true if the two ranges intersect
   bool DoesIntersect(const Range &rhs) const {
-    const BaseType lhs_base = this->GetRangeBase();
-    const BaseType rhs_base = rhs.GetRangeBase();
-    const BaseType lhs_end = this->GetRangeEnd();
-    const BaseType rhs_end = rhs.GetRangeEnd();
-    bool result = (lhs_base < rhs_end) && (lhs_end > rhs_base);
-    return result;
+    return Intersect(rhs).IsValid();
   }
 
   bool operator<(const Range &rhs) const {
@@ -133,6 +139,38 @@ template <typename B, typename S, unsigned N = 0> class RangeVector {
 
   ~RangeVector() = default;
 
+  static RangeVector GetOverlaps(const RangeVector &vec1,
+                                 const RangeVector &vec2) {
+#ifdef ASSERT_RANGEMAP_ARE_SORTED
+    assert(vec1.IsSorted() && vec2.IsSorted());
+#endif
+    RangeVector result;
+    auto pos1 = vec1.begin();
+    auto end1 = vec1.end();
+    auto pos2 = vec2.begin();
+    auto end2 = vec2.end();
+    while (pos1 != end1 && pos2 != end2) {
+      Entry entry = pos1->Intersect(*pos2);
+      if (entry.IsValid())
+        result.Append(entry);
+      if (pos1->GetRangeEnd() < pos2->GetRangeEnd())
+        ++pos1;
+      else
+        ++pos2;
+    }
+    return result;
+  }
+
+  bool operator==(const RangeVector &rhs) const {
+    if (GetSize() != rhs.GetSize())
+      return false;
+    for (size_t i = 0; i < GetSize(); ++i) {
+      if (GetEntryRef(i) != rhs.GetEntryRef(i))
+        return false;
+    }
+    return true;
+  }
+
   void Append(const Entry &entry) { m_entries.push_back(entry); }
 
   void Append(B base, S size) { m_entries.emplace_back(base, size); }

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
index d0672352a58fa..43ee9e1285b29 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -250,3 +250,29 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
   DWARFExpression result(nullptr, extractor, nullptr);
   return result;
 }
+
+DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpressionForClass(
+    llvm::ArrayRef<std::pair<RegisterId, uint32_t>> &members_info,
+    lldb::ModuleSP module) {
+  return MakeLocationExpressionInternal(
+      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
+        for (auto member_info : members_info) {
+          if (member_info.first != llvm::codeview::RegisterId::NONE) {
+            uint32_t reg_num =
+                GetRegisterNumber(module->GetArchitecture().GetMachine(),
+                                  member_info.first, register_kind);
+            if (reg_num == LLDB_INVALID_REGNUM)
+              return false;
+            if (reg_num > 31) {
+              stream.PutHex8(llvm::dwarf::DW_OP_regx);
+              stream.PutULEB128(reg_num);
+            } else {
+              stream.PutHex8(llvm::dwarf::DW_OP_reg0 + reg_num);
+            }
+          }
+          stream.PutHex8(llvm::dwarf::DW_OP_piece);
+          stream.PutULEB128(member_info.second);
+        }
+        return true;
+      });
+}

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
index 99da09b70fe1e..1f948452ad280 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
@@ -10,6 +10,7 @@
 #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_NATIVEPDB_DWARFLOCATIONEXPRESSION_H
 
 #include "lldb/lldb-forward.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 
 namespace llvm {
@@ -39,6 +40,10 @@ DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset,
 DWARFExpression MakeConstantLocationExpression(
     llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi,
     const llvm::APSInt &constant, lldb::ModuleSP module);
+DWARFExpression MakeEnregisteredLocationExpressionForClass(
+    llvm::ArrayRef<std::pair<llvm::codeview::RegisterId, uint32_t>>
+        &members_info,
+    lldb::ModuleSP module);
 } // namespace npdb
 } // namespace lldb_private
 

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index ddc52a6ec9276..c2c89bdf4ce83 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -497,7 +497,8 @@ clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
   if (isLocalVariableType(cvs.kind())) {
     clang::DeclContext *scope = GetParentDeclContext(id);
     clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
-    PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
+    PdbCompilandSymId scope_id =
+        PdbSymUid(m_decl_to_status[scope_decl].uid).asCompilandSym();
     return GetOrCreateVariableDecl(scope_id, id);
   }
 

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
index 6efad1219852c..5c184cef491f3 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -12,6 +12,7 @@
 #include "PdbIndex.h"
 #include "PdbSymUid.h"
 
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
@@ -20,6 +21,7 @@
 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
 #include "lldb/Symbol/Block.h"
 #include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/LLDBLog.h"
 #include "lldb/lldb-enumerations.h"
 
 using namespace lldb_private;
@@ -48,6 +50,22 @@ MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
   return result;
 }
 
+namespace {
+struct FindMembersSize : public TypeVisitorCallbacks {
+  FindMembersSize(std::vector<std::pair<RegisterId, uint32_t>> &members_info,
+                  TpiStream &tpi)
+      : members_info(members_info), tpi(tpi) {}
+  std::vector<std::pair<RegisterId, uint32_t>> &members_info;
+  TpiStream &tpi;
+  llvm::Error visitKnownMember(CVMemberRecord &cvr,
+                               DataMemberRecord &member) override {
+    members_info.emplace_back(llvm::codeview::RegisterId::NONE,
+                              GetSizeOfType(member.Type, tpi));
+    return llvm::Error::success();
+  }
+};
+} // namespace
+
 CVTagRecord CVTagRecord::create(CVType type) {
   assert(IsTagRecord(type) && "type is not a tag record!");
   switch (type.kind()) {
@@ -477,6 +495,8 @@ VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
     result.type = local.Type;
     result.name = local.Name;
+    result.is_param =
+        ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
     return result;
   }
 
@@ -609,7 +629,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
     PdbCompilandSymId loc_specifier_id(var_id.modi,
                                        var_id.offset + sym.RecordData.size());
     CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
-    if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
+    switch(loc_specifier_cvs.kind()) {
+    case S_DEFRANGE_FRAMEPOINTER_REL: {
       DefRangeFramePointerRelSym loc(
           SymbolRecordKind::DefRangeFramePointerRelSym);
       cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
@@ -632,10 +653,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
       PdbCompilandSymId frame_proc_id(
           func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
 
-      bool is_parameter =
-          ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
       RegisterId base_reg =
-          GetBaseFrameRegister(index, frame_proc_id, is_parameter);
+          GetBaseFrameRegister(index, frame_proc_id, result.is_param);
 
       if (base_reg == RegisterId::VFRAME) {
         llvm::StringRef program;
@@ -651,7 +670,9 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
             MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
         result.ranges = std::move(ranges);
       }
-    } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) {
+      break;
+    } 
+    case S_DEFRANGE_REGISTER_REL: {
       DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
       cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
           loc_specifier_cvs, loc));
@@ -674,9 +695,76 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
             base_reg, loc.Hdr.BasePointerOffset, module);
         result.ranges = std::move(ranges);
       }
+      break;
     }
+    case S_DEFRANGE_REGISTER: {
+      DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
+      cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
+          loc_specifier_cvs, loc));
 
-    // FIXME: Handle other kinds
+      RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
+      result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+      result.location = MakeEnregisteredLocationExpression(base_reg, module);
+      break;
+    }
+    case S_DEFRANGE_SUBFIELD_REGISTER: {
+      CVType class_cvt = index.tpi().getType(result.type);
+      ClassRecord class_record = CVTagRecord::create(class_cvt).asClass();
+      CVType field_list = index.tpi().getType(class_record.FieldList);
+      std::vector<std::pair<RegisterId, uint32_t>> members_info;
+      FindMembersSize find_members_size(members_info, index.tpi());
+      if (llvm::Error err =
+              visitMemberRecordStream(field_list.data(), find_members_size))
+        llvm::consumeError(std::move(err));
+
+      std::vector<Variable::RangeList> range_lists;
+      uint32_t cur_offset = 0;
+      size_t member_idx = 0;
+      // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by
+      // S_DEFRANGE_SUBFIELD_REGISTER, need to verify.
+      while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER &&
+             member_idx < members_info.size()) {
+        DefRangeSubfieldRegisterSym loc(
+            SymbolRecordKind::DefRangeSubfieldRegisterSym);
+        cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
+            loc_specifier_cvs, loc));
+
+        if (result.ranges) {
+          result.ranges = Variable::RangeList::GetOverlaps(
+              *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps));
+        } else {
+          result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+          result.ranges->Sort();
+        }
+
+        // Some fields maybe optimized away and have no
+        // S_DEFRANGE_SUBFIELD_REGISTER to describe them. Skip them.
+        while (loc.Hdr.OffsetInParent != cur_offset) {
+          cur_offset += members_info[member_idx].second;
+          ++member_idx;
+        }
+        if (member_idx < members_info.size()) {
+          members_info[member_idx].first =
+              (RegisterId)(uint16_t)loc.Hdr.Register;
+          cur_offset += members_info[member_idx].second;
+          ++member_idx;
+        }
+        // Go to next S_DEFRANGE_SUBFIELD_REGISTER.
+        loc_specifier_id = PdbCompilandSymId(
+            loc_specifier_id.modi,
+            loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
+        loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+      }
+      auto member_info_ref = llvm::makeArrayRef(members_info);
+      result.location =
+          MakeEnregisteredLocationExpressionForClass(member_info_ref, module);
+      break;
+    }
+    default:
+      // FIXME: Handle other kinds. LLVM only generates the 4 types of records
+      // above.
+      break;
+    }
     return result;
   }
   llvm_unreachable("Symbol is not a local variable!");

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
index c309c5c8ea1c8..138c11aaeb438 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -105,6 +105,7 @@ struct VariableInfo {
   llvm::codeview::TypeIndex type;
   llvm::Optional<DWARFExpression> location;
   llvm::Optional<Variable::RangeList> ranges;
+  bool is_param;
 };
 
 llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind);

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 14bb21b357086..411c7d902c21e 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1665,6 +1665,7 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
   SymbolFileTypeSP sftype =
       std::make_shared<SymbolFileType>(*this, type_sp->GetID());
 
+  is_param |= var_info.is_param;
   ValueType var_scope =
       is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
   bool external = false;
@@ -1673,7 +1674,7 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
   bool static_member = false;
   VariableSP var_sp = std::make_shared<Variable>(
       toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
-      comp_unit_sp.get(), *var_info.ranges, &decl, *var_info.location, external,
+      &block, *var_info.ranges, &decl, *var_info.location, external,
       artificial, location_is_constant_data, static_member);
 
   if (!is_param)

diff  --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp
index 190fdbee9e842..b92c866544969 100644
--- a/lldb/source/Symbol/Variable.cpp
+++ b/lldb/source/Symbol/Variable.cpp
@@ -243,6 +243,14 @@ bool Variable::LocationIsValidForAddress(const Address &address) {
   // Be sure to resolve the address to section offset prior to calling this
   // function.
   if (address.IsSectionOffset()) {
+    // We need to check if the address is valid for both scope range and value
+    // range. 
+    // Empty scope range means block range.
+    bool valid_in_scope_range =
+        GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains(
+                                         address.GetFileAddress()) != nullptr;
+    if (!valid_in_scope_range)
+      return false;
     SymbolContext sc;
     CalculateSymbolContext(&sc);
     if (sc.module_sp == address.GetModule()) {

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
new file mode 100644
index 0000000000000..7b35ebbc0f7c8
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
@@ -0,0 +1,11 @@
+image lookup -a 0x140001000 -v
+image lookup -a 0x140001003 -v
+image lookup -a 0x140001006 -v
+
+image lookup -a 0x140001011 -v
+image lookup -a 0x140001017 -v
+image lookup -a 0x140001019 -v
+image lookup -a 0x14000101e -v
+image lookup -a 0x14000102c -v
+
+exit

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
new file mode 100644
index 0000000000000..3be80e63a95dc
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
@@ -0,0 +1,477 @@
+# clang-format off
+# REQUIRES: lld, system-windows
+
+# RUN: %clang_cl --target=x86_64-windows-msvc /Fo%t.obj %s
+# RUN: lld-link /debug %t.obj /out:%t.exe /base:0x140000000
+# RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+# RUN:     %p/Inputs/local-variables-registers.lldbinit 2>&1 | FileCheck %s
+
+# This file is compiled from following source file:
+# clang-cl /Z7 /O1 /Falocal-variables-registers.s a.cpp
+# struct S {
+#   int x;
+#   char y;
+# };
+# 
+# __attribute__((noinline)) S CreateS(int p1, char p2) {
+#   S s;
+#   s.x = p1 + 1;
+#   s.y = p2 + 2;
+#   ++s.x;
+#   ++s.y;
+#   return s;
+# }
+# 
+# int main(int argc, char** argv) {
+#   int local = argc * 2;
+#   S s = CreateS(local, 'a');
+#   return s.x + s.y;
+# }
+
+# FIXME: The following variable location have wrong register numbers due to 
+# https://github.com/llvm/llvm-project/issues/53575. Fix them after resolving 
+# the issue.
+
+# CHECK:      (lldb) image lookup -a 0x140001000 -v
+# CHECK:          LineEntry: [0x0000000140001000-0x0000000140001003): C:\src\test\a.cpp:10
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p1", type = "int", valid ranges = [0x0000000140001000-0x0000000140001003), location = DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = [0x0000000140001000-0x0000000140001006), location = DW_OP_regx 0x3f
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001003 -v
+# CHECK:          LineEntry: [0x0000000140001003-0x0000000140001006): C:\src\test\a.cpp:11
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = [0x0000000140001000-0x0000000140001006), location = DW_OP_regx 0x3f
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001006 -v
+# CHECK:          LineEntry: [0x0000000140001006-0x0000000140001011): C:\src\test\a.cpp:12
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = [0x0000000140001006-0x0000000140001011), location = DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001011 -v
+# CHECK:          LineEntry: [0x0000000140001011-0x0000000140001015): C:\src\test\a.cpp:15
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001011-0x0000000140001017), location = DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001011-0x0000000140001019), location = DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001017 -v
+# CHECK:          LineEntry: [0x0000000140001017-0x000000014000101e): C:\src\test\a.cpp:17
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001011-0x0000000140001019), location = DW_OP_reg3 RBX
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = [0x0000000140001017-0x000000014000101e), location = DW_OP_reg26 XMM9
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001019 -v
+# CHECK:          LineEntry: [0x0000000140001017-0x000000014000101e): C:\src\test\a.cpp:17
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = [0x0000000140001017-0x000000014000101e), location = DW_OP_reg26 XMM9
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000101e -v
+# CHECK:          LineEntry: [0x000000014000101e-0x0000000140001031): C:\src\test\a.cpp:18
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = [0x000000014000101e-0x000000014000102c), location = DW_OP_reg24 XMM7, DW_OP_piece 0x4, DW_OP_piece 0x1
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000102c -v
+# CHECK:          LineEntry: [0x000000014000101e-0x0000000140001031): C:\src\test\a.cpp:18
+# CHECK-EMPTY:
+
+
+	.text
+	.def	 @feat.00;
+	.scl	3;
+	.type	0;
+	.endef
+	.globl	@feat.00
+.set @feat.00, 0
+	.intel_syntax noprefix
+	.file	"a.cpp"
+	.def	 "?CreateS@@YA?AUS@@HD at Z";
+	.scl	2;
+	.type	32;
+	.endef
+	.section	.text,"xr",one_only,"?CreateS@@YA?AUS@@HD at Z"
+	.globl	"?CreateS@@YA?AUS@@HD at Z"        # -- Begin function ?CreateS@@YA?AUS@@HD at Z
+"?CreateS@@YA?AUS@@HD at Z":               # @"?CreateS@@YA?AUS@@HD at Z"
+.Lfunc_begin0:
+	.cv_func_id 0
+# %bb.0:
+	#DEBUG_VALUE: CreateS:p2 <- $dl
+	#DEBUG_VALUE: CreateS:p1 <- $ecx
+	#DEBUG_VALUE: CreateS:s <- [DW_OP_plus_uconst 1, DW_OP_stack_value, DW_OP_LLVM_fragment 0 32] $ecx
+	#DEBUG_VALUE: CreateS:s <- [DW_OP_plus_uconst 2, DW_OP_stack_value, DW_OP_LLVM_fragment 32 8] $dl
+	.cv_file	1 "C:\\src\\test\\a.cpp" "446925B46C8C870B01708834F4813A31" 1
+	.cv_loc	0 1 10 0                        # a.cpp:10:0
+                                        # kill: def $ecx killed $ecx def $rcx
+	#DEBUG_VALUE: CreateS:s <- [DW_OP_plus_uconst 1, DW_OP_stack_value, DW_OP_LLVM_fragment 0 32] $ecx
+	add	ecx, 2
+.Ltmp0:
+	#DEBUG_VALUE: CreateS:p1 <- [DW_OP_LLVM_entry_value 1] $ecx
+	#DEBUG_VALUE: CreateS:s <- [DW_OP_LLVM_fragment 0 32] $ecx
+	.cv_loc	0 1 11 0                        # a.cpp:11:0
+	add	dl, 3
+.Ltmp1:
+	#DEBUG_VALUE: CreateS:p2 <- [DW_OP_LLVM_entry_value 1] $dl
+	#DEBUG_VALUE: CreateS:s <- [DW_OP_LLVM_fragment 32 8] $dl
+	.cv_loc	0 1 12 0                        # a.cpp:12:0
+	movzx	eax, dl
+	shl	rax, 32
+	or	rax, rcx
+	ret
+.Ltmp2:
+.Lfunc_end0:
+                                        # -- End function
+	.def	 main;
+	.scl	2;
+	.type	32;
+	.endef
+	.section	.text,"xr",one_only,main
+	.globl	main                            # -- Begin function main
+main:                                   # @main
+.Lfunc_begin1:
+	.cv_func_id 1
+	.cv_loc	1 1 15 0                        # a.cpp:15:0
+.seh_proc main
+# %bb.0:
+	#DEBUG_VALUE: main:argv <- $rdx
+	#DEBUG_VALUE: main:argc <- $ecx
+	sub	rsp, 40
+	.seh_stackalloc 40
+	.seh_endprologue
+.Ltmp3:
+	.cv_loc	1 1 16 0                        # a.cpp:16:0
+	add	ecx, ecx
+.Ltmp4:
+	#DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $ecx
+	#DEBUG_VALUE: main:local <- $ecx
+	.cv_loc	1 1 17 0                        # a.cpp:17:0
+	mov	dl, 97
+.Ltmp5:
+	#DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rdx
+	call	"?CreateS@@YA?AUS@@HD at Z"
+.Ltmp6:
+	#DEBUG_VALUE: main:s <- [DW_OP_LLVM_fragment 0 32] $eax
+	#DEBUG_VALUE: main:s <- [DW_OP_constu 40, DW_OP_shr, DW_OP_LLVM_convert 64 7, DW_OP_LLVM_convert 24 7, DW_OP_stack_value, DW_OP_LLVM_fragment 40 24] $rax
+	#DEBUG_VALUE: main:s <- [DW_OP_constu 32, DW_OP_shr, DW_OP_LLVM_convert 64 7, DW_OP_LLVM_convert 8 7, DW_OP_stack_value, DW_OP_LLVM_fragment 32 8] $rax
+	.cv_loc	1 1 18 0                        # a.cpp:18:0
+	mov	rcx, rax
+	shr	rcx, 8
+	sar	ecx, 24
+	add	ecx, eax
+	mov	eax, ecx
+.Ltmp7:
+	add	rsp, 40
+	ret
+.Ltmp8:
+.Lfunc_end1:
+	.seh_endproc
+                                        # -- End function
+	.section	.drectve,"yn"
+	.ascii	" /DEFAULTLIB:libcmt.lib"
+	.ascii	" /DEFAULTLIB:oldnames.lib"
+	.section	.debug$S,"dr"
+	.p2align	2
+	.long	4                               # Debug section magic
+	.long	241
+	.long	.Ltmp10-.Ltmp9                  # Subsection size
+.Ltmp9:
+	.short	.Ltmp12-.Ltmp11                 # Record length
+.Ltmp11:
+	.short	4412                            # Record kind: S_COMPILE3
+	.long	1                               # Flags and language
+	.short	208                             # CPUType
+	.short	13                              # Frontend version
+	.short	0
+	.short	0
+	.short	0
+	.short	13000                           # Backend version
+	.short	0
+	.short	0
+	.short	0
+	.asciz	"clang version 13.0.0"          # Null-terminated compiler version string
+	.p2align	2
+.Ltmp12:
+.Ltmp10:
+	.p2align	2
+	.section	.debug$S,"dr",associative,"?CreateS@@YA?AUS@@HD at Z"
+	.p2align	2
+	.long	4                               # Debug section magic
+	.long	241                             # Symbol subsection for CreateS
+	.long	.Ltmp14-.Ltmp13                 # Subsection size
+.Ltmp13:
+	.short	.Ltmp16-.Ltmp15                 # Record length
+.Ltmp15:
+	.short	4423                            # Record kind: S_GPROC32_ID
+	.long	0                               # PtrParent
+	.long	0                               # PtrEnd
+	.long	0                               # PtrNext
+	.long	.Lfunc_end0-"?CreateS@@YA?AUS@@HD at Z" # Code size
+	.long	0                               # Offset after prologue
+	.long	0                               # Offset before epilogue
+	.long	4103                            # Function type index
+	.secrel32	"?CreateS@@YA?AUS@@HD at Z" # Function section relative address
+	.secidx	"?CreateS@@YA?AUS@@HD at Z"        # Function section index
+	.byte	0                               # Flags
+	.asciz	"CreateS"                       # Function name
+	.p2align	2
+.Ltmp16:
+	.short	.Ltmp18-.Ltmp17                 # Record length
+.Ltmp17:
+	.short	4114                            # Record kind: S_FRAMEPROC
+	.long	0                               # FrameSize
+	.long	0                               # Padding
+	.long	0                               # Offset of padding
+	.long	0                               # Bytes of callee saved registers
+	.long	0                               # Exception handler offset
+	.short	0                               # Exception handler section
+	.long	0                               # Flags (defines frame register)
+	.p2align	2
+.Ltmp18:
+	.short	.Ltmp20-.Ltmp19                 # Record length
+.Ltmp19:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	116                             # TypeIndex
+	.short	1                               # Flags
+	.asciz	"p1"
+	.p2align	2
+.Ltmp20:
+	.cv_def_range	 .Lfunc_begin0 .Ltmp0, reg, 18
+	.short	.Ltmp22-.Ltmp21                 # Record length
+.Ltmp21:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	112                             # TypeIndex
+	.short	1                               # Flags
+	.asciz	"p2"
+	.p2align	2
+.Ltmp22:
+	.cv_def_range	 .Lfunc_begin0 .Ltmp1, reg, 3
+	.short	.Ltmp24-.Ltmp23                 # Record length
+.Ltmp23:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4100                            # TypeIndex
+	.short	0                               # Flags
+	.asciz	"s"
+	.p2align	2
+.Ltmp24:
+	.cv_def_range	 .Ltmp0 .Lfunc_end0, subfield_reg, 18, 0
+	.cv_def_range	 .Ltmp1 .Lfunc_end0, subfield_reg, 3, 4
+	.short	2                               # Record length
+	.short	4431                            # Record kind: S_PROC_ID_END
+.Ltmp14:
+	.p2align	2
+	.cv_linetable	0, "?CreateS@@YA?AUS@@HD at Z", .Lfunc_end0
+	.section	.debug$S,"dr",associative,main
+	.p2align	2
+	.long	4                               # Debug section magic
+	.long	241                             # Symbol subsection for main
+	.long	.Ltmp26-.Ltmp25                 # Subsection size
+.Ltmp25:
+	.short	.Ltmp28-.Ltmp27                 # Record length
+.Ltmp27:
+	.short	4423                            # Record kind: S_GPROC32_ID
+	.long	0                               # PtrParent
+	.long	0                               # PtrEnd
+	.long	0                               # PtrNext
+	.long	.Lfunc_end1-main                # Code size
+	.long	0                               # Offset after prologue
+	.long	0                               # Offset before epilogue
+	.long	4107                            # Function type index
+	.secrel32	main                    # Function section relative address
+	.secidx	main                            # Function section index
+	.byte	0                               # Flags
+	.asciz	"main"                          # Function name
+	.p2align	2
+.Ltmp28:
+	.short	.Ltmp30-.Ltmp29                 # Record length
+.Ltmp29:
+	.short	4114                            # Record kind: S_FRAMEPROC
+	.long	40                              # FrameSize
+	.long	0                               # Padding
+	.long	0                               # Offset of padding
+	.long	0                               # Bytes of callee saved registers
+	.long	0                               # Exception handler offset
+	.short	0                               # Exception handler section
+	.long	81920                           # Flags (defines frame register)
+	.p2align	2
+.Ltmp30:
+	.short	.Ltmp32-.Ltmp31                 # Record length
+.Ltmp31:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	116                             # TypeIndex
+	.short	1                               # Flags
+	.asciz	"argc"
+	.p2align	2
+.Ltmp32:
+	.cv_def_range	 .Lfunc_begin1 .Ltmp4, reg, 18
+	.short	.Ltmp34-.Ltmp33                 # Record length
+.Ltmp33:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4104                            # TypeIndex
+	.short	1                               # Flags
+	.asciz	"argv"
+	.p2align	2
+.Ltmp34:
+	.cv_def_range	 .Lfunc_begin1 .Ltmp5, reg, 331
+	.short	.Ltmp36-.Ltmp35                 # Record length
+.Ltmp35:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	116                             # TypeIndex
+	.short	0                               # Flags
+	.asciz	"local"
+	.p2align	2
+.Ltmp36:
+	.cv_def_range	 .Ltmp4 .Ltmp6, reg, 18
+	.short	.Ltmp38-.Ltmp37                 # Record length
+.Ltmp37:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4100                            # TypeIndex
+	.short	0                               # Flags
+	.asciz	"s"
+	.p2align	2
+.Ltmp38:
+	.cv_def_range	 .Ltmp6 .Ltmp7, subfield_reg, 17, 0
+	.short	2                               # Record length
+	.short	4431                            # Record kind: S_PROC_ID_END
+.Ltmp26:
+	.p2align	2
+	.cv_linetable	1, main, .Lfunc_end1
+	.section	.debug$S,"dr"
+	.long	241
+	.long	.Ltmp40-.Ltmp39                 # Subsection size
+.Ltmp39:
+	.short	.Ltmp42-.Ltmp41                 # Record length
+.Ltmp41:
+	.short	4360                            # Record kind: S_UDT
+	.long	4100                            # Type
+	.asciz	"S"
+	.p2align	2
+.Ltmp42:
+.Ltmp40:
+	.p2align	2
+	.cv_filechecksums                       # File index to string table offset subsection
+	.cv_stringtable                         # String table
+	.long	241
+	.long	.Ltmp44-.Ltmp43                 # Subsection size
+.Ltmp43:
+	.short	.Ltmp46-.Ltmp45                 # Record length
+.Ltmp45:
+	.short	4428                            # Record kind: S_BUILDINFO
+	.long	4110                            # LF_BUILDINFO index
+	.p2align	2
+.Ltmp46:
+.Ltmp44:
+	.p2align	2
+	.section	.debug$T,"dr"
+	.p2align	2
+	.long	4                               # Debug section magic
+	# Struct (0x1000)
+	.short	0x1e                            # Record length
+	.short	0x1505                          # Record kind: LF_STRUCTURE
+	.short	0x0                             # MemberCount
+	.short	0x280                           # Properties ( ForwardReference (0x80) | HasUniqueName (0x200) )
+	.long	0x0                             # FieldList
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x0                             # SizeOf
+	.asciz	"S"                             # Name
+	.asciz	".?AUS@@"                       # LinkageName
+	# ArgList (0x1001)
+	.short	0xe                             # Record length
+	.short	0x1201                          # Record kind: LF_ARGLIST
+	.long	0x2                             # NumArgs
+	.long	0x74                            # Argument: int
+	.long	0x70                            # Argument: char
+	# Procedure (0x1002)
+	.short	0xe                             # Record length
+	.short	0x1008                          # Record kind: LF_PROCEDURE
+	.long	0x1000                          # ReturnType: S
+	.byte	0x0                             # CallingConvention: NearC
+	.byte	0x0                             # FunctionOptions
+	.short	0x2                             # NumParameters
+	.long	0x1001                          # ArgListType: (int, char)
+	# FieldList (0x1003)
+	.short	0x1a                            # Record length
+	.short	0x1203                          # Record kind: LF_FIELDLIST
+	.short	0x150d                          # Member kind: DataMember ( LF_MEMBER )
+	.short	0x3                             # Attrs: Public
+	.long	0x74                            # Type: int
+	.short	0x0                             # FieldOffset
+	.asciz	"x"                             # Name
+	.short	0x150d                          # Member kind: DataMember ( LF_MEMBER )
+	.short	0x3                             # Attrs: Public
+	.long	0x70                            # Type: char
+	.short	0x4                             # FieldOffset
+	.asciz	"y"                             # Name
+	# Struct (0x1004)
+	.short	0x1e                            # Record length
+	.short	0x1505                          # Record kind: LF_STRUCTURE
+	.short	0x2                             # MemberCount
+	.short	0x200                           # Properties ( HasUniqueName (0x200) )
+	.long	0x1003                          # FieldList: <field list>
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x8                             # SizeOf
+	.asciz	"S"                             # Name
+	.asciz	".?AUS@@"                       # LinkageName
+	# StringId (0x1005)
+	.short	0x1a                            # Record length
+	.short	0x1605                          # Record kind: LF_STRING_ID
+	.long	0x0                             # Id
+	.asciz	"C:\\src\\test\\a.cpp"          # StringData
+	.byte	242
+	.byte	241
+	# UdtSourceLine (0x1006)
+	.short	0xe                             # Record length
+	.short	0x1606                          # Record kind: LF_UDT_SRC_LINE
+	.long	0x1004                          # UDT: S
+	.long	0x1005                          # SourceFile: C:\src\test\a.cpp
+	.long	0x1                             # LineNumber
+	# FuncId (0x1007)
+	.short	0x12                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x1002                          # FunctionType: S (int, char)
+	.asciz	"CreateS"                       # Name
+	# Pointer (0x1008)
+	.short	0xa                             # Record length
+	.short	0x1002                          # Record kind: LF_POINTER
+	.long	0x670                           # PointeeType: char*
+	.long	0x1000c                         # Attrs: [ Type: Near64, Mode: Pointer, SizeOf: 8 ]
+	# ArgList (0x1009)
+	.short	0xe                             # Record length
+	.short	0x1201                          # Record kind: LF_ARGLIST
+	.long	0x2                             # NumArgs
+	.long	0x74                            # Argument: int
+	.long	0x1008                          # Argument: char**
+	# Procedure (0x100A)
+	.short	0xe                             # Record length
+	.short	0x1008                          # Record kind: LF_PROCEDURE
+	.long	0x74                            # ReturnType: int
+	.byte	0x0                             # CallingConvention: NearC
+	.byte	0x0                             # FunctionOptions
+	.short	0x2                             # NumParameters
+	.long	0x1009                          # ArgListType: (int, char**)
+	# FuncId (0x100B)
+	.short	0x12                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x100a                          # FunctionType: int (int, char**)
+	.asciz	"main"                          # Name
+	.byte	243
+	.byte	242
+	.byte	241
+	# StringId (0x100C)
+	.short	0x12                            # Record length
+	.short	0x1605                          # Record kind: LF_STRING_ID
+	.long	0x0                             # Id
+	.asciz	"C:\\src\\test"                 # StringData
+	# StringId (0x100D)
+	.short	0xe                             # Record length
+	.short	0x1605                          # Record kind: LF_STRING_ID
+	.long	0x0                             # Id
+	.asciz	"a.cpp"                         # StringData
+	.byte	242
+	.byte	241
+	# BuildInfo (0x100E)
+	.short	0x1a                            # Record length
+	.short	0x1603                          # Record kind: LF_BUILDINFO
+	.short	0x5                             # NumArgs
+	.long	0x100c                          # Argument: C:\src\test
+	.long	0x0                             # Argument
+	.long	0x100d                          # Argument: a.cpp
+	.long	0x0                             # Argument
+	.long	0x0                             # Argument
+	.byte	242
+	.byte	241
+	.addrsig

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
index 701b843fa1228..e96e3ed6a0107 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
@@ -24,19 +24,19 @@ int main(int argc, char **argv) {
 
 // CHECK: (lldb) thread backtrace
 // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
+// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
 // CHECK-NEXT:     frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
 
 
 // CHECK: (lldb) thread backtrace
 // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
-// CHECK-NEXT:     frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
+// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT:     frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
 // CHECK-NEXT:     frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
 
 // CHECK: (lldb) thread backtrace
 // CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
-// CHECK-NEXT:     frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
-// CHECK-NEXT:     frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method at stack_unwinding01.cpp:12
+// CHECK-NEXT:   * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT:     frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT:     frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
 // CHECK-NEXT:     frame #3: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20

diff  --git a/lldb/unittests/Utility/RangeMapTest.cpp b/lldb/unittests/Utility/RangeMapTest.cpp
index 97432dca983d3..0b4c236062f20 100644
--- a/lldb/unittests/Utility/RangeMapTest.cpp
+++ b/lldb/unittests/Utility/RangeMapTest.cpp
@@ -38,6 +38,61 @@ TEST(RangeVector, CombineConsecutiveRanges) {
   EXPECT_THAT(V, testing::ElementsAre(Entry(0, 20)));
 }
 
+TEST(RangeVector, GetOverlaps) {
+  using RangeVector = RangeVector<uint32_t, uint32_t>;
+
+  RangeVector V1;
+  RangeVector V2;
+  RangeVector Expected;
+  // same range
+  V1.Append(0, 1);
+  V2.Append(0, 1);
+  Expected.Append(0, 1);
+
+  // no overlap
+  V1.Append(2, 2);
+  V2.Append(4, 1);
+
+  // same base overlap
+  V1.Append(10, 5);
+  V2.Append(10, 3);
+  Expected.Append(10, 3);
+
+  // same end overlap
+  V1.Append(27, 1);
+  V2.Append(20, 8);
+  Expected.Append(27, 1);
+
+  // smaller base overlap
+  V1.Append(33, 4);
+  V2.Append(30, 5);
+  Expected.Append(33, 2);
+
+  // larger base overlap
+  V1.Append(46, 3);
+  V2.Append(40, 7);
+  Expected.Append(46, 1);
+
+  // encompass 1 range
+  V1.Append(50, 9);
+  V2.Append(51, 7);
+  Expected.Append(51, 7);
+
+  // encompass 2 ranges
+  V1.Append(60, 9);
+  V2.Append(60, 3);
+  V2.Append(65, 3);
+  Expected.Append(60, 3);
+  Expected.Append(65, 3);
+
+  V1.Sort();
+  V2.Sort();
+  Expected.Sort();
+
+  EXPECT_EQ(RangeVector::GetOverlaps(V1, V2), Expected);
+  EXPECT_EQ(RangeVector::GetOverlaps(V2, V1), Expected);
+}
+
 using RangeDataVectorT = RangeDataVector<uint32_t, uint32_t, uint32_t>;
 using EntryT = RangeDataVectorT::Entry;
 


        


More information about the lldb-commits mailing list