summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZequan Wu <zequanwu@google.com>2022-02-10 18:18:59 -0800
committerZequan Wu <zequanwu@google.com>2022-03-10 12:40:31 -0800
commit5e9c9b324a1f7f904b733852d0a05a43e9783cbb (patch)
tree365f4c16ea246fd973e5c6512a9f6f4d2c95167c
parent2f33f11428c1832a413d5ca617948ac5cc397385 (diff)
[LLDB][NativePDB] Add support for S_DEFRANGE_REGISTER and S_DEFRANGE_SUBFIELD_REGISTER
Differential Revision: https://reviews.llvm.org/D119508
-rw-r--r--lldb/include/lldb/Utility/RangeMap.h50
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp26
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h5
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp3
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp100
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h1
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp3
-rw-r--r--lldb/source/Symbol/Variable.cpp8
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit11
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s477
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp12
-rw-r--r--lldb/unittests/Utility/RangeMapTest.cpp55
12 files changed, 731 insertions, 20 deletions
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 422f90d807a7..7eb0cab8084c 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 @@ public:
~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 d0672352a58f..43ee9e1285b2 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 99da09b70fe1..1f948452ad28 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 ddc52a6ec927..c2c89bdf4ce8 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 6efad1219852..5c184cef491f 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 c309c5c8ea1c..138c11aaeb43 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 14bb21b35708..411c7d902c21 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 190fdbee9e84..b92c86654496 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 000000000000..7b35ebbc0f7c
--- /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 000000000000..3be80e63a95d
--- /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@Z";
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text,"xr",one_only,"?CreateS@@YA?AUS@@HD@Z"
+ .globl "?CreateS@@YA?AUS@@HD@Z" # -- Begin function ?CreateS@@YA?AUS@@HD@Z
+"?CreateS@@YA?AUS@@HD@Z": # @"?CreateS@@YA?AUS@@HD@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@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@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@Z" # Code size
+ .long 0 # Offset after prologue
+ .long 0 # Offset before epilogue
+ .long 4103 # Function type index
+ .secrel32 "?CreateS@@YA?AUS@@HD@Z" # Function section relative address
+ .secidx "?CreateS@@YA?AUS@@HD@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@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 701b843fa122..e96e3ed6a010 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 97432dca983d..0b4c236062f2 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;