[Lldb-commits] [lldb] 71d778f - [LLDB][NativePDB] Switch to use DWARFLocationList.
Zequan Wu via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 17 13:37:21 PDT 2022
Author: Zequan Wu
Date: 2022-08-17T13:37:13-07:00
New Revision: 71d778f33e8615f525f118db351c6541b40199ab
URL: https://github.com/llvm/llvm-project/commit/71d778f33e8615f525f118db351c6541b40199ab
DIFF: https://github.com/llvm/llvm-project/commit/71d778f33e8615f525f118db351c6541b40199ab.diff
LOG: [LLDB][NativePDB] Switch to use DWARFLocationList.
Before, NativePDB uses scoped range as a workaround for value range, that causes
problems (e.g. a variable's value can only have one range, but usually a
variable's value is located at different address ranges, each at different
locations, in optimized build).
This patch let NativePDB switch to DWARFLocationList so a variable's value can
be described at multiple non-overlapped address ranges and each range maps to a
location.
Because overlapping ranges exists, here's peference when choosing ranges:
1. Always prefer whole value locations. Suppose a variable size is 8 bytes, one record is that for range [1, 5) first 4 bytes is at ecx, and another record is that for range [2, 8) the 8 bytes value is at rdx. This results: [1, 2) has first 4 bytes at ecx, [2, 8) has the whole value at rdx.
2. Always prefer the locations parsed later. Suppose first record is that for range [1, 5) value is at ecx, second record is that for range [2, 6) value is at eax. This results: [1, 2) -> ecx, [2, 6) -> eax.
Differential Revision: https://reviews.llvm.org/D130796
Added:
Modified:
lldb/include/lldb/Utility/RangeMap.h
lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
Removed:
lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s
################################################################################
diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h
index 257b177c70927..54c86648fc51c 100644
--- a/lldb/include/lldb/Utility/RangeMap.h
+++ b/lldb/include/lldb/Utility/RangeMap.h
@@ -49,6 +49,11 @@ template <typename B, typename S> struct Range {
void Slide(BaseType slide) { base += slide; }
+ void ShrinkFront(S s) {
+ base += s;
+ size -= std::min(s, size);
+ }
+
bool Union(const Range &rhs) {
if (DoesAdjoinOrIntersect(rhs)) {
auto new_end = std::max<BaseType>(GetRangeEnd(), rhs.GetRangeEnd());
@@ -445,6 +450,13 @@ class RangeDataVector {
void Append(const Entry &entry) { m_entries.emplace_back(entry); }
+ bool Erase(uint32_t start, uint32_t end) {
+ if (start >= end || end > m_entries.size())
+ return false;
+ m_entries.erase(begin() + start, begin() + end);
+ return true;
+ }
+
void Sort() {
if (m_entries.size() > 1)
std::stable_sort(m_entries.begin(), m_entries.end(),
@@ -621,6 +633,17 @@ class RangeDataVector {
return nullptr;
}
+ uint32_t FindEntryIndexThatContainsOrFollows(B addr) const {
+#ifdef ASSERT_RANGEMAP_ARE_SORTED
+ assert(IsSorted());
+#endif
+ const AugmentedEntry *entry = static_cast<const AugmentedEntry *>(
+ FindEntryThatContainsOrFollows(addr));
+ if (entry)
+ return std::distance(m_entries.begin(), entry);
+ return UINT32_MAX;
+ }
+
Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
const Entry *Back() const {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
index 3d8030916c84f..d98e3c4c761a3 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
@@ -649,3 +649,100 @@ uint32_t lldb_private::npdb::GetLLDBRegisterNumber(
return LLDB_INVALID_REGNUM;
}
}
+
+uint32_t
+lldb_private::npdb::GetRegisterSize(llvm::codeview::RegisterId register_id) {
+ switch(register_id) {
+ case llvm::codeview::RegisterId::AL:
+ case llvm::codeview::RegisterId::BL:
+ case llvm::codeview::RegisterId::CL:
+ case llvm::codeview::RegisterId::DL:
+ case llvm::codeview::RegisterId::AH:
+ case llvm::codeview::RegisterId::BH:
+ case llvm::codeview::RegisterId::CH:
+ case llvm::codeview::RegisterId::DH:
+ case llvm::codeview::RegisterId::SIL:
+ case llvm::codeview::RegisterId::DIL:
+ case llvm::codeview::RegisterId::BPL:
+ case llvm::codeview::RegisterId::SPL:
+ case llvm::codeview::RegisterId::R8B:
+ case llvm::codeview::RegisterId::R9B:
+ case llvm::codeview::RegisterId::R10B:
+ case llvm::codeview::RegisterId::R11B:
+ case llvm::codeview::RegisterId::R12B:
+ case llvm::codeview::RegisterId::R13B:
+ case llvm::codeview::RegisterId::R14B:
+ case llvm::codeview::RegisterId::R15B:
+ return 1;
+ case llvm::codeview::RegisterId::AX:
+ case llvm::codeview::RegisterId::BX:
+ case llvm::codeview::RegisterId::CX:
+ case llvm::codeview::RegisterId::DX:
+ case llvm::codeview::RegisterId::SP:
+ case llvm::codeview::RegisterId::BP:
+ case llvm::codeview::RegisterId::SI:
+ case llvm::codeview::RegisterId::DI:
+ case llvm::codeview::RegisterId::R8W:
+ case llvm::codeview::RegisterId::R9W:
+ case llvm::codeview::RegisterId::R10W:
+ case llvm::codeview::RegisterId::R11W:
+ case llvm::codeview::RegisterId::R12W:
+ case llvm::codeview::RegisterId::R13W:
+ case llvm::codeview::RegisterId::R14W:
+ case llvm::codeview::RegisterId::R15W:
+ return 2;
+ case llvm::codeview::RegisterId::EAX:
+ case llvm::codeview::RegisterId::EBX:
+ case llvm::codeview::RegisterId::ECX:
+ case llvm::codeview::RegisterId::EDX:
+ case llvm::codeview::RegisterId::ESP:
+ case llvm::codeview::RegisterId::EBP:
+ case llvm::codeview::RegisterId::ESI:
+ case llvm::codeview::RegisterId::EDI:
+ case llvm::codeview::RegisterId::R8D:
+ case llvm::codeview::RegisterId::R9D:
+ case llvm::codeview::RegisterId::R10D:
+ case llvm::codeview::RegisterId::R11D:
+ case llvm::codeview::RegisterId::R12D:
+ case llvm::codeview::RegisterId::R13D:
+ case llvm::codeview::RegisterId::R14D:
+ case llvm::codeview::RegisterId::R15D:
+ return 4;
+ case llvm::codeview::RegisterId::RAX:
+ case llvm::codeview::RegisterId::RBX:
+ case llvm::codeview::RegisterId::RCX:
+ case llvm::codeview::RegisterId::RDX:
+ case llvm::codeview::RegisterId::RSI:
+ case llvm::codeview::RegisterId::RDI:
+ case llvm::codeview::RegisterId::RBP:
+ case llvm::codeview::RegisterId::RSP:
+ case llvm::codeview::RegisterId::R8:
+ case llvm::codeview::RegisterId::R9:
+ case llvm::codeview::RegisterId::R10:
+ case llvm::codeview::RegisterId::R11:
+ case llvm::codeview::RegisterId::R12:
+ case llvm::codeview::RegisterId::R13:
+ case llvm::codeview::RegisterId::R14:
+ case llvm::codeview::RegisterId::R15:
+ return 8;
+ case llvm::codeview::RegisterId::XMM0:
+ case llvm::codeview::RegisterId::XMM1:
+ case llvm::codeview::RegisterId::XMM2:
+ case llvm::codeview::RegisterId::XMM3:
+ case llvm::codeview::RegisterId::XMM4:
+ case llvm::codeview::RegisterId::XMM5:
+ case llvm::codeview::RegisterId::XMM6:
+ case llvm::codeview::RegisterId::XMM7:
+ case llvm::codeview::RegisterId::XMM8:
+ case llvm::codeview::RegisterId::XMM9:
+ case llvm::codeview::RegisterId::XMM10:
+ case llvm::codeview::RegisterId::XMM11:
+ case llvm::codeview::RegisterId::XMM12:
+ case llvm::codeview::RegisterId::XMM13:
+ case llvm::codeview::RegisterId::XMM14:
+ case llvm::codeview::RegisterId::XMM15:
+ return 16;
+ default:
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
index 02c7495565b86..1ed4fde9df320 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
@@ -17,6 +17,7 @@ namespace npdb {
uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
llvm::codeview::RegisterId register_id);
+uint32_t GetRegisterSize(llvm::codeview::RegisterId register_id);
} // namespace npdb
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
index 3166c8ae65c6c..b1436575d881c 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -128,33 +128,38 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
return result;
}
+static bool MakeRegisterBasedLocationExpressionInternal(
+ Stream &stream, llvm::codeview::RegisterId reg, RegisterKind register_kind,
+ llvm::Optional<int32_t> relative_offset, lldb::ModuleSP module) {
+ uint32_t reg_num = GetRegisterNumber(module->GetArchitecture().GetMachine(),
+ reg, register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ if (reg_num > 31) {
+ llvm::dwarf::LocationAtom base =
+ relative_offset ? llvm::dwarf::DW_OP_bregx : llvm::dwarf::DW_OP_regx;
+ stream.PutHex8(base);
+ stream.PutULEB128(reg_num);
+ } else {
+ llvm::dwarf::LocationAtom base =
+ relative_offset ? llvm::dwarf::DW_OP_breg0 : llvm::dwarf::DW_OP_reg0;
+ stream.PutHex8(base + reg_num);
+ }
+
+ if (relative_offset)
+ stream.PutSLEB128(*relative_offset);
+
+ return true;
+}
+
static DWARFExpression MakeRegisterBasedLocationExpressionInternal(
llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
lldb::ModuleSP module) {
return MakeLocationExpressionInternal(
module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
- uint32_t reg_num = GetRegisterNumber(
- module->GetArchitecture().GetMachine(), reg, register_kind);
- if (reg_num == LLDB_INVALID_REGNUM)
- return false;
-
- if (reg_num > 31) {
- llvm::dwarf::LocationAtom base = relative_offset
- ? llvm::dwarf::DW_OP_bregx
- : llvm::dwarf::DW_OP_regx;
- stream.PutHex8(base);
- stream.PutULEB128(reg_num);
- } else {
- llvm::dwarf::LocationAtom base = relative_offset
- ? llvm::dwarf::DW_OP_breg0
- : llvm::dwarf::DW_OP_reg0;
- stream.PutHex8(base + reg_num);
- }
-
- if (relative_offset)
- stream.PutSLEB128(*relative_offset);
-
- return true;
+ return MakeRegisterBasedLocationExpressionInternal(
+ stream, reg, register_kind, relative_offset, module);
});
}
@@ -251,28 +256,43 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
return result;
}
-DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpressionForClass(
- std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
+DWARFExpression
+lldb_private::npdb::MakeEnregisteredLocationExpressionForComposite(
+ const std::map<uint64_t, MemberValLocation> &offset_to_location,
+ std::map<uint64_t, size_t> &offset_to_size, size_t total_size,
lldb::ModuleSP module) {
return MakeLocationExpressionInternal(
module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool {
- for (auto pair : members_info) {
- std::pair<RegisterId, uint32_t> member_info = pair.second;
- 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);
- }
+ size_t cur_offset = 0;
+ bool is_simple_type = offset_to_size.empty();
+ // Iterate through offset_to_location because offset_to_size might be
+ // empty if the variable is a simple type.
+ for (const auto &offset_loc : offset_to_location) {
+ if (cur_offset < offset_loc.first) {
+ stream.PutHex8(llvm::dwarf::DW_OP_piece);
+ stream.PutULEB128(offset_loc.first - cur_offset);
+ cur_offset = offset_loc.first;
}
+ MemberValLocation loc = offset_loc.second;
+ llvm::Optional<int32_t> offset =
+ loc.is_at_reg ? llvm::None
+ : llvm::Optional<int32_t>(loc.reg_offset);
+ if (!MakeRegisterBasedLocationExpressionInternal(
+ stream, (RegisterId)loc.reg_id, register_kind, offset,
+ module))
+ return false;
+ if (!is_simple_type) {
+ stream.PutHex8(llvm::dwarf::DW_OP_piece);
+ stream.PutULEB128(offset_to_size[offset_loc.first]);
+ cur_offset = offset_loc.first + offset_to_size[offset_loc.first];
+ }
+ }
+ // For simple type, it specifies the byte size of the value described by
+ // the previous dwarf expr. For udt, it's the remaining byte size at end
+ // of a struct.
+ if (total_size > cur_offset) {
stream.PutHex8(llvm::dwarf::DW_OP_piece);
- stream.PutULEB128(member_info.second);
+ stream.PutULEB128(total_size - cur_offset);
}
return true;
});
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
index 1ed6c55fea74b..2f12d8bf0dd78 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
@@ -26,6 +26,12 @@ class TpiStream;
} // namespace llvm
namespace lldb_private {
namespace npdb {
+struct MemberValLocation {
+ uint16_t reg_id;
+ uint16_t reg_offset;
+ bool is_at_reg = true;
+};
+
DWARFExpression
MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg,
lldb::ModuleSP module);
@@ -41,9 +47,9 @@ 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(
- std::map<uint64_t, std::pair<llvm::codeview::RegisterId, uint32_t>>
- &members_info,
+DWARFExpression MakeEnregisteredLocationExpressionForComposite(
+ const std::map<uint64_t, MemberValLocation> &offset_to_location,
+ std::map<uint64_t, size_t> &offset_to_size, size_t total_size,
lldb::ModuleSP module);
} // namespace npdb
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
index 7d730ecdd1f33..387182cc46a97 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -19,6 +19,7 @@
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
@@ -29,6 +30,8 @@ using namespace lldb_private::npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;
+// The returned range list is guaranteed to be sorted and no overlaps between
+// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
static Variable::RangeList
MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
llvm::ArrayRef<LocalVariableAddrGap> gaps) {
@@ -52,21 +55,144 @@ MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
}
namespace {
-struct FindMembersSize : public TypeVisitorCallbacks {
- FindMembersSize(
- std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
- TpiStream &tpi)
- : members_info(members_info), tpi(tpi) {}
- std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info;
- TpiStream &tpi;
- llvm::Error visitKnownMember(CVMemberRecord &cvr,
- DataMemberRecord &member) override {
- members_info.insert(
- {member.getFieldOffset(),
- {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}});
- return llvm::Error::success();
+struct MemberLocations {
+ std::map<uint64_t, MemberValLocation> offset_to_location;
+ DWARFExpression expr;
+ bool is_dwarf = false;
+
+ MemberLocations() = default;
+ MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
+ MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
+ insert(offset, member_loc);
}
+
+ void insert(uint64_t offset, const MemberValLocation &member_loc) {
+ offset_to_location[offset] = member_loc;
+ }
+
+ struct Comparator {
+ public:
+ bool operator()(const MemberLocations &, const MemberLocations &) const {
+ return false;
+ }
+ };
};
+
+// A range map with address ranges to a map of pair of offset and locaitons.
+typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
+ MemberLocations::Comparator>
+ RangeMap;
+
+void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
+ MemberValLocation member_loc,
+ const Variable::RangeList &ranges) {
+ RangeMap new_location_map;
+ auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
+ RangeMap::Entry *entry) {
+ RangeMap::Entry overlap_region = {base, end - base, entry->data};
+ overlap_region.data.insert(offset, member_loc);
+ new_location_map.Append(overlap_region);
+ };
+
+ for (const auto &range : ranges) {
+ lldb::addr_t base = range.GetRangeBase();
+ lldb::addr_t end = range.GetRangeEnd();
+ uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
+ while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
+ if (base >= end || entry->base >= end)
+ break;
+ if (entry->data.is_dwarf)
+ base = entry->GetRangeEnd();
+ else {
+ lldb::addr_t entry_end = entry->GetRangeEnd();
+ if (base > entry->base) {
+ if (end < entry_end)
+ new_location_map.Append({end, entry_end - end, entry->data});
+ add_overlap_region(base, end < entry_end ? end : entry_end, entry);
+ entry->SetRangeEnd(base);
+ } else if (base < entry->base) {
+ new_location_map.Append(
+ {base, entry->base - base, {offset, member_loc}});
+ if (entry_end == end)
+ entry->data.insert(offset, member_loc);
+ else {
+ add_overlap_region(entry->base, end, entry);
+ entry->ShrinkFront(end - entry->base);
+ }
+ } else {
+ if (end < entry_end) {
+ new_location_map.Append({end, entry_end, entry->data});
+ entry->SetRangeEnd(end);
+ }
+ entry->data.insert(offset, member_loc);
+ }
+ base = entry_end;
+ }
+ ++base_idx;
+ }
+ if (base >= end)
+ continue;
+ new_location_map.Append({base, end - base, {offset, member_loc}});
+ }
+ for (const auto &entry : new_location_map)
+ location_map.Append(entry);
+ if (!new_location_map.IsEmpty())
+ location_map.Sort();
+}
+
+void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
+ const Variable::RangeList &ranges) {
+ if (!expr.IsValid())
+ return;
+ RangeMap new_location_map;
+ for (const auto &range : ranges) {
+ lldb::addr_t base = range.GetRangeBase();
+ lldb::addr_t end = range.GetRangeEnd();
+ uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
+ uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
+ // range is within an entry.
+ if (base_idx == end_idx && base_idx != UINT32_MAX) {
+ auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
+ if (base > entry->base) {
+ new_location_map.Append({entry->base, base - entry->base, entry->data});
+ entry->ShrinkFront(base - entry->base);
+ }
+ if (end == entry->GetRangeEnd())
+ entry->data = expr;
+ else {
+ entry->ShrinkFront(end - base);
+ new_location_map.Append({base, end - base, expr});
+ }
+ continue;
+ }
+ base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
+ if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
+ if (entry->Contains(base) && entry->base != base) {
+ entry->SetRangeEnd(base);
+ ++base_idx;
+ }
+ }
+ end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
+ if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
+ if (entry->Contains(end - 1)) {
+ if (entry->GetRangeEnd() == end)
+ ++end_idx;
+ else
+ entry->ShrinkFront(end - entry->base);
+ }
+ }
+
+ if (end_idx == UINT32_MAX)
+ end_idx = location_map.GetSize();
+ // Erase existing ranges covered by new range.
+ location_map.Erase(base_idx, end_idx);
+ new_location_map.Append({base, end - base, expr});
+ }
+
+ for (const auto &entry : new_location_map)
+ location_map.Append(entry);
+ location_map.Sort();
+}
} // namespace
CVTagRecord CVTagRecord::create(CVType type) {
@@ -612,207 +738,176 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
if (sym.kind() == S_REGREL32) {
RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
- result.location =
- MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
- result.ranges.emplace();
+ result.location = DWARFExpressionList(
+ module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
+ nullptr);
return result;
}
if (sym.kind() == S_REGISTER) {
RegisterSym reg(SymbolRecordKind::RegisterSym);
cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
- result.location = MakeEnregisteredLocationExpression(reg.Register, module);
- result.ranges.emplace();
+ result.location = DWARFExpressionList(
+ module, MakeEnregisteredLocationExpression(reg.Register, module),
+ nullptr);
return result;
}
if (sym.kind() == S_LOCAL) {
LocalSym local(SymbolRecordKind::LocalSym);
- cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+ if (llvm::Error error =
+ SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
+ llvm::consumeError(std::move(error));
+ return result;
+ }
PdbCompilandSymId loc_specifier_id(var_id.modi,
var_id.offset + sym.RecordData.size());
- CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
- switch(loc_specifier_cvs.kind()) {
- case S_DEFRANGE_FRAMEPOINTER_REL: {
- DefRangeFramePointerRelSym loc(
- SymbolRecordKind::DefRangeFramePointerRelSym);
- cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
- loc_specifier_cvs, loc));
-
- Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-
- PdbCompilandSymId func_scope_id =
- PdbSymUid(func_block.GetID()).asCompilandSym();
- CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
- lldbassert(func_block_cvs.kind() == S_GPROC32 ||
- func_block_cvs.kind() == S_LPROC32);
-
- PdbCompilandSymId frame_proc_id(
- func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
-
- RegisterId base_reg =
- GetBaseFrameRegister(index, frame_proc_id, result.is_param);
- if (base_reg == RegisterId::NONE)
- break;
- if (base_reg == RegisterId::VFRAME) {
- llvm::StringRef program;
- if (GetFrameDataProgram(index, ranges, program)) {
- result.location =
- MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module);
- result.ranges = std::move(ranges);
- } else {
- // invalid variable
+ CVSymbol loc_specifier_cvs;
+ // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
+ RegisterId base_reg = RegisterId::NONE;
+ size_t type_size = GetSizeOfType(result.type, index.tpi());
+ // A map from offset of a field in parent to size of the field.
+ std::map<uint64_t, size_t> offset_to_size;
+
+ // When overlaps happens, always prefer the one that doesn't split the value
+ // into multiple locations and the location parsed first is perfered.
+ RangeMap location_map;
+
+ // Iterate through all location records after S_LOCAL. They describe the
+ // value of this variable at
diff erent locations.
+ bool finished = false;
+ while (!finished) {
+ loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+ switch (loc_specifier_cvs.kind()) {
+ case S_DEFRANGE_FRAMEPOINTER_REL: {
+ DefRangeFramePointerRelSym loc(
+ SymbolRecordKind::DefRangeFramePointerRelSym);
+ if (llvm::Error error =
+ SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
+ loc_specifier_cvs, loc)) {
+ llvm::consumeError(std::move(error));
+ return result;
+ }
+ Variable::RangeList raw_ranges =
+ MakeRangeList(index, loc.Range, loc.Gaps);
+ if (base_reg == RegisterId::NONE) {
+ PdbCompilandSymId func_scope_id =
+ PdbSymUid(func_block.GetID()).asCompilandSym();
+ CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
+ lldbassert(func_block_cvs.kind() == S_GPROC32 ||
+ func_block_cvs.kind() == S_LPROC32);
+ PdbCompilandSymId frame_proc_id(func_scope_id.modi,
+ func_scope_id.offset +
+ func_block_cvs.length());
+ base_reg =
+ GetBaseFrameRegister(index, frame_proc_id, result.is_param);
+ if (base_reg == RegisterId::NONE)
+ break;
}
- } else {
- result.location =
- MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
- result.ranges = std::move(ranges);
+ DWARFExpression expr;
+ if (base_reg == RegisterId::VFRAME) {
+ llvm::StringRef program;
+ if (GetFrameDataProgram(index, raw_ranges, program))
+ expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
+ module);
+ else {
+ // invalid variable
+ }
+ } else
+ expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
+ AddDwarfRange(location_map, expr, raw_ranges);
+ break;
}
- break;
- }
- case S_DEFRANGE_REGISTER_REL: {
- DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
- cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
- loc_specifier_cvs, loc));
-
- Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-
- RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
-
- if (base_reg == RegisterId::VFRAME) {
- llvm::StringRef program;
- if (GetFrameDataProgram(index, ranges, program)) {
- result.location = MakeVFrameRelLocationExpression(
- program, loc.Hdr.BasePointerOffset, module);
- result.ranges = std::move(ranges);
- } else {
- // invalid variable
+ case S_DEFRANGE_REGISTER: {
+ DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
+ if (llvm::Error error =
+ SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
+ loc_specifier_cvs, loc)) {
+ llvm::consumeError(std::move(error));
+ return result;
}
- } else {
- result.location = MakeRegRelLocationExpression(
- base_reg, loc.Hdr.BasePointerOffset, module);
- result.ranges = std::move(ranges);
+ RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
+ Variable::RangeList raw_ranges =
+ MakeRangeList(index, loc.Range, loc.Gaps);
+ DWARFExpression expr =
+ MakeEnregisteredLocationExpression(reg_id, module);
+ AddDwarfRange(location_map, expr, raw_ranges);
+ break;
}
- break;
- }
- case S_DEFRANGE_REGISTER: {
- DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
- cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
- loc_specifier_cvs, loc));
-
- 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: {
- // A map from offset in parent to pair of register id and size. If the
- // variable is a simple type, then we don't know the number of subfields.
- // Otherwise, the size of the map should be greater than or equal to the
- // number of sub field record.
- std::map<uint64_t, std::pair<RegisterId, uint32_t>> members_info;
- bool is_simple_type = result.type.isSimple();
- if (!is_simple_type) {
- CVType class_cvt = index.tpi().getType(result.type);
- TypeIndex class_id = result.type;
- if (class_cvt.kind() == LF_MODIFIER)
- class_id = LookThroughModifierRecord(class_cvt);
- if (IsForwardRefUdt(class_id, index.tpi())) {
- auto expected_full_ti =
- index.tpi().findFullDeclForForwardRef(class_id);
- if (!expected_full_ti) {
- llvm::consumeError(expected_full_ti.takeError());
- break;
- }
- class_cvt = index.tpi().getType(*expected_full_ti);
+ case S_DEFRANGE_REGISTER_REL: {
+ DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
+ if (llvm::Error error =
+ SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
+ loc_specifier_cvs, loc)) {
+ llvm::consumeError(std::move(error));
+ return result;
}
- if (IsTagRecord(class_cvt)) {
- TagRecord tag_record = CVTagRecord::create(class_cvt).asTag();
- CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
- FieldListRecord field_list;
- if (llvm::Error error =
- TypeDeserializer::deserializeAs<FieldListRecord>(
- field_list_cvt, field_list))
- llvm::consumeError(std::move(error));
- FindMembersSize find_members_size(members_info, index.tpi());
- if (llvm::Error err = visitMemberRecordStream(field_list.Data,
- find_members_size)) {
- llvm::consumeError(std::move(err));
- break;
+ Variable::RangeList raw_ranges =
+ MakeRangeList(index, loc.Range, loc.Gaps);
+ RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
+ DWARFExpression expr;
+ if (reg_id == RegisterId::VFRAME) {
+ llvm::StringRef program;
+ if (GetFrameDataProgram(index, raw_ranges, program))
+ expr = MakeVFrameRelLocationExpression(
+ program, loc.Hdr.BasePointerOffset, module);
+ else {
+ // invalid variable
}
} else {
- // TODO: Handle poiner type.
- break;
+ expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
+ module);
}
+ // FIXME: If it's UDT, we need to know the size of the value in byte.
+ if (!loc.hasSpilledUDTMember())
+ AddDwarfRange(location_map, expr, raw_ranges);
+ break;
}
-
- 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) {
- if (!is_simple_type && member_idx >= members_info.size())
- break;
-
+ case S_DEFRANGE_SUBFIELD_REGISTER: {
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();
+ if (llvm::Error error =
+ SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
+ loc_specifier_cvs, loc)) {
+ llvm::consumeError(std::move(error));
+ return result;
}
- if (is_simple_type) {
- if (members_info.count(loc.Hdr.OffsetInParent)) {
- // Malformed record.
- result.ranges->Clear();
- return result;
- }
- members_info[loc.Hdr.OffsetInParent] = {
- (RegisterId)(uint16_t)loc.Hdr.Register, 0};
- } else {
- if (!members_info.count(loc.Hdr.OffsetInParent)) {
- // Malformed record.
- result.ranges->Clear();
- return result;
- }
- members_info[loc.Hdr.OffsetInParent].first =
- (RegisterId)(uint16_t)loc.Hdr.Register;
- }
- // 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);
+ Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+ uint32_t reg_size =
+ GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
+ if (reg_size == 0)
+ break;
+ offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
+ AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
+ {loc.Hdr.Register, 0, true}, ranges);
+ break;
}
- // Fix size for simple type.
- if (is_simple_type) {
- auto cur = members_info.begin();
- auto end = members_info.end();
- auto next = cur;
- ++next;
- uint32_t size = 0;
- while (next != end) {
- cur->second.second = next->first - cur->first;
- size += cur->second.second;
- cur = next++;
- }
- cur->second.second =
- GetTypeSizeForSimpleKind(result.type.getSimpleKind()) - size;
+ // FIXME: Handle other kinds. LLVM only generates the 4 types of records
+ // above. MSVC generates other location types.
+ case S_DEFRANGE:
+ case S_DEFRANGE_SUBFIELD:
+ case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
+ break;
+ default:
+ finished = true;
+ break;
}
- result.location =
- MakeEnregisteredLocationExpressionForClass(members_info, module);
- break;
+ loc_specifier_id = PdbCompilandSymId(
+ loc_specifier_id.modi,
+ loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
}
- default:
- // FIXME: Handle other kinds. LLVM only generates the 4 types of records
- // above.
- break;
+ result.location = DWARFExpressionList();
+ for (const auto &entry : location_map) {
+ DWARFExpression dwarf_expr =
+ entry.data.is_dwarf ? entry.data.expr
+ : MakeEnregisteredLocationExpressionForComposite(
+ entry.data.offset_to_location,
+ offset_to_size, type_size, module);
+
+ result.location->AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
+ dwarf_expr);
}
return result;
}
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
index 066bcc89fd3b7..fa078ca061a8c 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -103,8 +103,7 @@ struct SegmentOffsetLength {
struct VariableInfo {
llvm::StringRef name;
llvm::codeview::TypeIndex type;
- llvm::Optional<DWARFExpression> location;
- llvm::Optional<Variable::RangeList> ranges;
+ llvm::Optional<DWARFExpressionList> location;
bool is_param;
};
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index cf17e616f659f..4109f6b7d4fa0 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1712,9 +1712,13 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
func_block->GetStartAddress(addr);
VariableInfo var_info =
GetVariableLocationInfo(*m_index, var_id, *func_block, module);
- if (!var_info.location || !var_info.ranges)
+ if (!var_info.location || var_info.location->GetSize() == 0)
return nullptr;
-
+ Function *func = func_block->CalculateSymbolContextFunction();
+ if (!func)
+ return VariableSP();
+ var_info.location->SetFuncFileAddress(
+ func->GetAddressRange().GetBaseAddress().GetFileAddress());
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
TypeSP type_sp = GetOrCreateType(var_info.type);
@@ -1732,11 +1736,10 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
bool artificial = false;
bool location_is_constant_data = false;
bool static_member = false;
- DWARFExpressionList locaiton_list = DWARFExpressionList(
- module, *var_info.location, nullptr);
+ Variable::RangeList scope_ranges;
VariableSP var_sp = std::make_shared<Variable>(
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
- &block, *var_info.ranges, &decl, locaiton_list, external, artificial,
+ &block, scope_ranges, &decl, *var_info.location, external, artificial,
location_is_constant_data, static_member);
if (!is_param)
m_ast->GetOrCreateVariableDecl(scope_id, var_id);
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
index 7b35ebbc0f7c8..ad080da24dab7 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
+++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
@@ -8,4 +8,28 @@ image lookup -a 0x140001019 -v
image lookup -a 0x14000101e -v
image lookup -a 0x14000102c -v
+image lookup -a 0x140001031 -v
+image lookup -a 0x140001032 -v
+image lookup -a 0x140001033 -v
+image lookup -a 0x140001034 -v
+image lookup -a 0x140001035 -v
+image lookup -a 0x140001036 -v
+image lookup -a 0x140001037 -v
+image lookup -a 0x14000103b -v
+image lookup -a 0x14000103d -v
+image lookup -a 0x14000103f -v
+image lookup -a 0x140001041 -v
+image lookup -a 0x140001043 -v
+image lookup -a 0x140001045 -v
+image lookup -a 0x140001046 -v
+image lookup -a 0x140001047 -v
+image lookup -a 0x140001048 -v
+image lookup -a 0x140001049 -v
+image lookup -a 0x14000104a -v
+image lookup -a 0x14000104b -v
+image lookup -a 0x14000104c -v
+image lookup -a 0x14000104e -v
+image lookup -a 0x14000104f -v
+image lookup -a 0x140001050 -v
+image lookup -a 0x140001051 -v
exit
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
index 70e344e60aa9a..6fd4186e98846 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
+++ b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
@@ -52,13 +52,17 @@
#CHECK: (lldb) b a.cpp:4
#CHECK: Breakpoint 13: where = {{.*}}`main + 61 at a.cpp:4, address = 0x000000014000103d
+# 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.
+
# CEHCK-LABEL: (lldb) image lookup -a 0x140001003 -v
# CHECK: Summary: {{.*}}`main + 3 at a.cpp:2
# CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046)
# CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
# CHECK: LineEntry: [0x0000000140001000-0x0000000140001004): /tmp/a.cpp:2
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
# CEHCK-LABEL: (lldb) image lookup -a 0x140001004 -v
# CHECK: Summary: {{.*}}`main + 4 [inlined] Namespace1::foo at a.h:5
@@ -67,10 +71,10 @@
# CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
# CHECK: LineEntry: [0x0000000140001004-0x000000014000100c): /tmp/a.h:5
-# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CEHCK-LABEL: (lldb) image lookup -a 0x140001010 -v
# CHECK: Summary: {{.*}}`main + 16 [inlined] Namespace1::foo + 12 at a.h:7
@@ -79,10 +83,10 @@
# CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
# CHECK: LineEntry: [0x0000000140001010-0x0000000140001018): /tmp/a.h:7
-# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CEHCK-LABEL: (lldb) image lookup -a 0x14000101c -v
# CHECK: Summary: {{.*}}`main + 28 [inlined] Class1::bar at b.h:5
@@ -93,12 +97,12 @@
# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
# CHECK-NEXT: id = {{.*}}, range = [0x14000101c-0x140001039), name = "Class1::bar", decl = b.h:4
# CHECK: LineEntry: [0x000000014000101c-0x0000000140001022): /tmp/b.h:5
-# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int", valid ranges = [0x000000014000101c-0x000000014000101e)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = [0x000000014000101c-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x000000014000101e) -> DW_OP_reg24 XMM7
+# CHECK-NEXT: Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x0000000140001039) -> DW_OP_breg7 RSP+52
+# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CEHCK-LABEL: (lldb) image lookup -a 0x14000102a -v
# CHECK: Summary: {{.*}}`main + 42 [inlined] Namespace2::Class2::func at c.h:5
@@ -111,21 +115,21 @@
# CHECK-NEXT: id = {{.*}}, range = [0x14000101c-0x140001039), name = "Class1::bar", decl = b.h:4
# CHECK-NEXT: id = {{.*}}, range = [0x14000102a-0x140001039), name = "Namespace2::Class2::func", decl = c.h:4
# CHECK: LineEntry: [0x000000014000102a-0x0000000140001031): /tmp/c.h:5
-# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int", valid ranges = [0x000000014000102a-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "func_local", type = "int", valid ranges = [0x000000014000102a-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = [0x000000014000101c-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int", valid ranges = <block>, location = [0x000000014000102a, 0x0000000140001039) -> DW_OP_reg24 XMM7
+# CHECK-NEXT: Variable: id = {{.*}}, name = "func_local", type = "int", valid ranges = <block>, location = [0x000000014000102a, 0x0000000140001039) -> DW_OP_breg7 RSP+48
+# CHECK-NEXT: Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x0000000140001039) -> DW_OP_breg7 RSP+52
+# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CEHCK-LABEL: (lldb) image lookup -a 0x140001039 -v
# CHECK: Summary: {{.*}}`main + 57 at a.cpp:3
# CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046)
# CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
# CHECK: LineEntry: [0x0000000140001039-0x000000014000103d): /tmp/a.cpp:3
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CEHCK-LABEL: (lldb) image lookup -a 0x140001044 -v
# CHECK: Summary: {{.*}}`main + 68 [inlined] Namespace1::foo + 5 at a.h:8
@@ -134,10 +138,10 @@
# CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
# CHECK: LineEntry: [0x0000000140001044-0x0000000140001046): /tmp/a.h:8
-# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001044-0x0000000140001046)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001044-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT: Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001044, 0x0000000140001046) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001044, 0x0000000140001045) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
# CHECK-LABEL: (lldb) target modules dump ast
# CHECK-NEXT: Dumping clang ast for 1 modules.
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
index ad524dd98c46a..ad2d0704cdf41 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
+++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
@@ -34,39 +34,38 @@
# 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-NEXT: Variable: id = {{.*}}, name = "p1", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001003) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001006) -> 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-NEXT: Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001006) -> DW_OP_regx 0x3f
+# CHECK-NEXT: Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x0000000140001003, 0x0000000140001006) -> DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3
# 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-NEXT: Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x0000000140001006, 0x0000000140001011) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3
# 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-NEXT: Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001017) -> DW_OP_reg26 XMM9
+# CHECK-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001019) -> 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-NEXT: Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001019) -> DW_OP_reg3 RBX
+# CHECK-NEXT: Variable: id = {{.*}}, name = "local", type = "int", valid ranges = <block>, location = [0x0000000140001017, 0x000000014000101e) -> 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-NEXT: Variable: id = {{.*}}, name = "local", type = "int", valid ranges = <block>, location = [0x0000000140001017, 0x000000014000101e) -> 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-NEXT: Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x000000014000101e, 0x000000014000102c) -> DW_OP_reg24 XMM7, DW_OP_piece 0x4, DW_OP_piece 0x4
# 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;
@@ -153,6 +152,75 @@ main: # @main
.Ltmp7:
add rsp, 40
ret
+# Manually created for testing purpose.
+.L31:
+ .cv_loc 1 1 1000 0 # a.cpp:1000:0
+ ret
+.L32:
+ ret
+.L33:
+ ret
+.L34:
+ .cv_loc 1 1 1001 0 # a.cpp:1001:0
+ ret
+.L35:
+ ret
+.L36:
+ ret
+.L37:
+ ret
+.L38:
+ ret
+.L39:
+ ret
+.L3a:
+ ret
+.L3b:
+ .cv_loc 1 1 1002 0 # a.cpp:1002:0
+ ret
+.L3c:
+ ret
+.L3d:
+ ret
+.L3e:
+ ret
+.L3f:
+ ret
+.L40:
+ ret
+.L41:
+ ret
+.L42:
+ ret
+.L43:
+ ret
+.L44:
+ ret
+.L45:
+ .cv_loc 1 1 1003 0 # a.cpp:1003:0
+ ret
+.L46:
+ ret
+.L47:
+ ret
+.L48:
+ ret
+.L49:
+ ret
+.L4a:
+ ret
+.L4b:
+ ret
+.L4c:
+ ret
+.L4d:
+ ret
+.L4e:
+ .cv_loc 1 1 1004 0 # a.cpp:1004:0
+ ret
+.L4f:
+ ret
+.L50:
.Ltmp8:
.Lfunc_end1:
.seh_endproc
@@ -322,8 +390,172 @@ main: # @main
.p2align 2
.Ltmp38:
.cv_def_range .Ltmp6 .Ltmp7, subfield_reg, 17, 0
- .short 2 # Record length
+ .short .Ltmp101-.Ltmp100
+# Manually created debug info for testing purpose.
+# 1. Test non-overlapped ranges.
+.Ltmp100:
+ .short 4414 # Record kind: S_LOCAL
+ .long 4109 # TypeIndex
+ .short 0 # Flags
+ .asciz "non_overlapped_ranges"
+ .p2align 2
+.Ltmp101:
+ .cv_def_range .L31 .L32, reg, 331
+ .cv_def_range .L32 .L33, reg, 330
+ .cv_def_range .L33 .L34, reg, 336
+ .short .Ltmp103-.Ltmp102
+# CHECK: (lldb) image lookup -a 0x140001031 -v
+# CHECK: LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT: Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001031, 0x0000000140001032) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001032 -v
+# CHECK: LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT: Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001032, 0x0000000140001033) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001033 -v
+# CHECK: LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT: Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001033, 0x0000000140001034) -> DW_OP_reg8 R8
+# CHECK-EMPTY:
+
+# 2. Test overlapped subfield ranges at
diff erent offsets.
+.Ltmp102:
+ .short 4414 # Record kind: S_LOCAL
+ .long 4109 # TypeIndex
+ .short 0 # Flags
+ .asciz "overlapped_subfield_ranges"
+ .p2align 2
+.Ltmp103:
+ .cv_def_range .L34 .L36, subfield_reg, 3, 0
+ .cv_def_range .L35 .L37, subfield_reg, 17, 4
+ .cv_def_range .L37 .L39, subfield_reg, 18, 4
+ .short .Ltmp105-.Ltmp104
+# CHECK: (lldb) image lookup -a 0x140001034 -v
+# CHECK: LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001034, 0x0000000140001035) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x7
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001035 -v
+# CHECK: LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001035, 0x0000000140001036) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001036 -v
+# CHECK: LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001036, 0x0000000140001037) -> DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001037 -v
+# CHECK: LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001037, 0x0000000140001039) -> DW_OP_piece 0x4, DW_OP_reg26 XMM9, DW_OP_piece 0x4
+# CHECK-EMPTY:
+
+# 3. Test overlapped ranges for the whole value.
+.Ltmp104:
+ .short 4414 # Record kind: S_LOCAL
+ .long 4109 # TypeIndex
+ .short 0 # Flags
+ .asciz "overlapped_ranges_2"
+ .p2align 2
+.Ltmp105:
+ .cv_def_range .L3b .L3d, reg, 331
+ .cv_def_range .L3c .L3e, reg, 330
+ .cv_def_range .L3f .L44, reg, 339
+ .cv_def_range .L41 .L43, reg, 328
+ .short .Ltmp107-.Ltmp106
+# CHECK: (lldb) image lookup -a 0x14000103b -v
+# CHECK: LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103b, 0x000000014000103c) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000103d -v
+# CHECK: LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103c, 0x000000014000103e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000103f -v
+# CHECK: LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103f, 0x0000000140001041) -> DW_OP_reg11 R11
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001041 -v
+# CHECK: LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x0000000140001041, 0x0000000140001043) -> DW_OP_reg0 RAX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001043 -v
+# CHECK: LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x0000000140001043, 0x0000000140001044) -> DW_OP_reg11 R11
+# CHECK-EMPTY:
+
+# 4. Test overlapped ranges for both subfield and whole value.
+.Ltmp106:
+ .short 4414 # Record kind: S_LOCAL
+ .long 4109 # TypeIndex
+ .short 0 # Flags
+ .asciz "overlapped_ranges_3"
+ .p2align 2
+.Ltmp107:
+ # The following two lines result:
+ # [.L45, .L46) -> value at offset 0 is at reg 3.
+ # [.L46, .L49) -> value at offset 0 is at reg 3 and value at offset 4 is at reg 17.
+ # [.L49, .L4a) -> value at offset 4 is at reg 17.
+ .cv_def_range .L46 .L4a, subfield_reg, 17, 4
+ .cv_def_range .L45 .L49, subfield_reg, 3, 0
+ # The following overwrites range [.L47, .L48) and [.L49 .L4a) because whole
+ # value location is preferred over composited value locations.
+ .cv_def_range .L47 .L48, reg, 331
+ .cv_def_range .L49 .L4a, reg, 328
+ # For the same reason, reg 330 wins in following example.
+ .cv_def_range .L4b .L4e, reg, 330
+ .cv_def_range .L4b .L4d, subfield_reg, 17, 4
+ .cv_def_range .L4c .L4e, subfield_reg, 3, 0
+ .short .Ltmp109-.Ltmp108
+# CHECK: (lldb) image lookup -a 0x140001045 -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001045, 0x0000000140001046) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x7
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001046 -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001046, 0x0000000140001047) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001047 -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001047, 0x0000000140001048) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001048 -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001048, 0x0000000140001049) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x140001049 -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001049, 0x000000014000104a) -> DW_OP_reg0 RAX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000104a -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000104b -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x000000014000104b, 0x000000014000104e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000104c -v
+# CHECK: LineEntry: [0x0000000140001045-0x000000014000104e): C:\src\test\a.cpp:1003
+# CHECK-NEXT: Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x000000014000104b, 0x000000014000104e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+
+# 5. Simple type with subfield.
+.Ltmp108:
+ .short 4414 # Record kind: S_LOCAL
+ .long 19 # TypeIndex
+ .short 0 # Flags
+ .asciz "simple_type1"
+ .p2align 2
+.Ltmp109:
+ .cv_def_range .L4e .L4f, subfield_reg, 17, 4
+ .cv_def_range .L4e .L50, subfield_reg, 18, 0
+ .short 2
.short 4431 # Record kind: S_PROC_ID_END
+# CHECK: (lldb) image lookup -a 0x14000104e -v
+# CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004
+# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104e, 0x000000014000104f) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK: (lldb) image lookup -a 0x14000104f -v
+# CHECK: LineEntry: [0x000000014000104e-0x0000000140001050): C:\src\test\a.cpp:1004
+# CHECK-NEXT: Variable: id = {{.*}}, name = "simple_type1", type = "int64_t", valid ranges = <block>, location = [0x000000014000104f, 0x0000000140001050) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_piece 0x4
+# CHECK-EMPTY:
+
.Ltmp26:
.p2align 2
.cv_linetable 1, main, .Lfunc_end1
@@ -452,25 +684,38 @@ main: # @main
.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
+ # Manually created debug info for testing purpose, FieldList (0x100C) and Struct (0x100D)
+ # FieldList (0x100C)
+ .short 0x1a # Record length
+ .short 0x1203 # Record kind: LF_FIELDLIST
+ .short 0x150d # Member kind: DataMember ( LF_MEMBER )
+ .short 0x3 # Attrs: Public
+ .long 0x70 # Type: char
+ .short 0x0 # FieldOffset
+ .asciz "c" # Name
+ .short 0x150d # Member kind: DataMember ( LF_MEMBER )
+ .short 0x3 # Attrs: Public
+ .long 0x74 # Type: int
+ .short 0x4 # FieldOffset
+ .asciz "i" # Name
+ # Struct (0x100D)
+ .short 0x20 # Record length
+ .short 0x1505 # Record kind: LF_STRUCTURE
+ .short 0x2 # MemberCount
+ .short 0x200 # Properties ( HasUniqueName (0x200) )
+ .long 0x100c # FieldList: <field list>
+ .long 0x0 # DerivedFrom
+ .long 0x0 # VShape
+ .short 0x8 # SizeOf
+ .asciz "S1" # Name
+ .asciz ".?AUS1@@" # LinkageName
# BuildInfo (0x100E)
.short 0x1a # Record length
.short 0x1603 # Record kind: LF_BUILDINFO
- .short 0x5 # NumArgs
- .long 0x100c # Argument: C:\src\test
+ .short 0x1 # NumArgs
+ .long 0x0 # Argument
+ .long 0x0 # Argument
.long 0x0 # Argument
- .long 0x100d # Argument: a.cpp
.long 0x0 # Argument
.long 0x0 # Argument
.byte 242
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s b/lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s
deleted file mode 100644
index 80fa421188a09..0000000000000
--- a/lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s
+++ /dev/null
@@ -1,433 +0,0 @@
-# clang-format off
-# REQUIRES: lld, x86
-
-# RUN: %clang_cl --target=i386-windows-msvc -c /Fo%t.obj -- %s
-# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe /base:0x400000
-# RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
-# RUN: %p/Inputs/subfield_register_simple_type.lldbinit 2>&1 | FileCheck %s
-
-# This file is compiled from following source file:
-# clang-cl --target=i386-windows-msvc /Z7 /O1 -c /Fa a.cpp
-# __int64 __attribute__((optnone)) bar(__int64 x) { return x; };
-# __int64 foo(__int64 x) {
-# return bar(x);
-# }
-#
-# int main(int argc, char** argv) {
-# foo(argc);
-# return 0;
-# }
-
-# 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 0x40102f -v
-# CHECK: LineEntry: [0x00401026-0x00401039): C:\src\a.cpp:3
-# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int64_t", valid ranges = [0x0040102f-0x00401036), location = DW_OP_reg0 EAX, DW_OP_piece 0x4, DW_OP_reg2 EDX, DW_OP_piece 0x4, decl =
-
- .text
- .def @feat.00;
- .scl 3;
- .type 0;
- .endef
- .globl @feat.00
-.set @feat.00, 1
- .intel_syntax noprefix
- .file "a.cpp"
- .def "?bar@@YA_J_J at Z";
- .scl 2;
- .type 32;
- .endef
- .section .text,"xr",one_only,"?bar@@YA_J_J at Z"
- .globl "?bar@@YA_J_J at Z" # -- Begin function ?bar@@YA_J_J at Z
- .p2align 4, 0x90
-"?bar@@YA_J_J at Z": # @"?bar@@YA_J_J at Z"
-Lfunc_begin0:
- .cv_func_id 0
- .cv_file 1 "C:\\src\\a.cpp" "CB99424BC3DD1AB059A2DBC6841147F2" 1
- .cv_loc 0 1 1 0 # a.cpp:1:0
- .cv_fpo_proc "?bar@@YA_J_J at Z" 8
-# %bb.0: # %entry
- push ebp
- .cv_fpo_pushreg ebp
- mov ebp, esp
- .cv_fpo_setframe ebp
- and esp, -8
- .cv_fpo_stackalign 8
- sub esp, 8
- .cv_fpo_stackalloc 8
- .cv_fpo_endprologue
- mov eax, dword ptr [ebp + 8]
- mov ecx, dword ptr [ebp + 12]
- mov dword ptr [esp], eax
- mov dword ptr [esp + 4], ecx
-Ltmp0:
- mov eax, dword ptr [esp]
- mov edx, dword ptr [esp + 4]
- mov esp, ebp
- pop ebp
- ret
-Ltmp1:
- .cv_fpo_endproc
-Lfunc_end0:
- # -- End function
- .def "?foo@@YA_J_J at Z";
- .scl 2;
- .type 32;
- .endef
- .section .text,"xr",one_only,"?foo@@YA_J_J at Z"
- .globl "?foo@@YA_J_J at Z" # -- Begin function ?foo@@YA_J_J at Z
-"?foo@@YA_J_J at Z": # @"?foo@@YA_J_J at Z"
-Lfunc_begin1:
- .cv_func_id 1
- .cv_fpo_proc "?foo@@YA_J_J at Z" 8
-# %bb.0: # %entry
- #DEBUG_VALUE: foo:x <- [DW_OP_plus_uconst 4] [$esp+0]
- .cv_loc 1 1 3 0 # a.cpp:3:0
- jmp "?bar@@YA_J_J at Z" # TAILCALL
-Ltmp2:
- .cv_fpo_endproc
-Lfunc_end1:
- # -- End function
- .def _main;
- .scl 2;
- .type 32;
- .endef
- .section .text,"xr",one_only,_main
- .globl _main # -- Begin function main
-_main: # @main
-Lfunc_begin2:
- .cv_func_id 2
- .cv_loc 2 1 6 0 # a.cpp:6:0
- .cv_fpo_proc _main 8
-# %bb.0: # %entry
- #DEBUG_VALUE: main:argv <- [DW_OP_plus_uconst 8] [$esp+0]
- #DEBUG_VALUE: main:argc <- [DW_OP_plus_uconst 4] [$esp+0]
- .cv_inline_site_id 3 within 2 inlined_at 1 7 0
- .cv_loc 3 1 3 0 # a.cpp:3:0
- mov eax, dword ptr [esp + 4]
- mov ecx, eax
- sar ecx, 31
-Ltmp3:
- #DEBUG_VALUE: foo:x <- [DW_OP_LLVM_fragment 0 32] $eax
- #DEBUG_VALUE: foo:x <- [DW_OP_LLVM_fragment 32 32] $ecx
- push ecx
-Ltmp4:
- push eax
- call "?bar@@YA_J_J at Z"
-Ltmp5:
- add esp, 8
-Ltmp6:
- .cv_loc 2 1 8 0 # a.cpp:8:0
- xor eax, eax
- ret
-Ltmp7:
- .cv_fpo_endproc
-Lfunc_end2:
- # -- 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 Ltmp9-Ltmp8 # Subsection size
-Ltmp8:
- .short Ltmp11-Ltmp10 # Record length
-Ltmp10:
- .short 4353 # Record kind: S_OBJNAME
- .long 0 # Signature
- .asciz "C:\\src\\a.obj" # Object name
- .p2align 2
-Ltmp11:
- .short Ltmp13-Ltmp12 # Record length
-Ltmp12:
- .short 4412 # Record kind: S_COMPILE3
- .long 1 # Flags and language
- .short 7 # CPUType
- .short 15 # Frontend version
- .short 0
- .short 0
- .short 0
- .short 15000 # Backend version
- .short 0
- .short 0
- .short 0
- .asciz "clang version 15.0.0" # Null-terminated compiler version string
- .p2align 2
-Ltmp13:
-Ltmp9:
- .p2align 2
- .long 246 # Inlinee lines subsection
- .long Ltmp15-Ltmp14 # Subsection size
-Ltmp14:
- .long 0 # Inlinee lines signature
-
- # Inlined function foo starts at a.cpp:2
- .long 4098 # Type index of inlined function
- .cv_filechecksumoffset 1 # Offset into filechecksum table
- .long 2 # Starting line number
-Ltmp15:
- .p2align 2
- .section .debug$S,"dr",associative,"?bar@@YA_J_J at Z"
- .p2align 2
- .long 4 # Debug section magic
- .cv_fpo_data "?bar@@YA_J_J at Z"
- .long 241 # Symbol subsection for bar
- .long Ltmp17-Ltmp16 # Subsection size
-Ltmp16:
- .short Ltmp19-Ltmp18 # Record length
-Ltmp18:
- .short 4423 # Record kind: S_GPROC32_ID
- .long 0 # PtrParent
- .long 0 # PtrEnd
- .long 0 # PtrNext
- .long Lfunc_end0-"?bar@@YA_J_J at Z" # Code size
- .long 0 # Offset after prologue
- .long 0 # Offset before epilogue
- .long 4099 # Function type index
- .secrel32 "?bar@@YA_J_J at Z" # Function section relative address
- .secidx "?bar@@YA_J_J at Z" # Function section index
- .byte 0 # Flags
- .asciz "bar" # Function name
- .p2align 2
-Ltmp19:
- .short Ltmp21-Ltmp20 # Record length
-Ltmp20:
- .short 4114 # Record kind: S_FRAMEPROC
- .long 12 # 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 147456 # Flags (defines frame register)
- .p2align 2
-Ltmp21:
- .short Ltmp23-Ltmp22 # Record length
-Ltmp22:
- .short 4414 # Record kind: S_LOCAL
- .long 19 # TypeIndex
- .short 1 # Flags
- .asciz "x"
- .p2align 2
-Ltmp23:
- .cv_def_range Ltmp0 Ltmp1, reg_rel, 30006, 0, -8
- .short 2 # Record length
- .short 4431 # Record kind: S_PROC_ID_END
-Ltmp17:
- .p2align 2
- .cv_linetable 0, "?bar@@YA_J_J at Z", Lfunc_end0
- .section .debug$S,"dr",associative,"?foo@@YA_J_J at Z"
- .p2align 2
- .long 4 # Debug section magic
- .cv_fpo_data "?foo@@YA_J_J at Z"
- .long 241 # Symbol subsection for foo
- .long Ltmp25-Ltmp24 # Subsection size
-Ltmp24:
- .short Ltmp27-Ltmp26 # Record length
-Ltmp26:
- .short 4423 # Record kind: S_GPROC32_ID
- .long 0 # PtrParent
- .long 0 # PtrEnd
- .long 0 # PtrNext
- .long Lfunc_end1-"?foo@@YA_J_J at Z" # Code size
- .long 0 # Offset after prologue
- .long 0 # Offset before epilogue
- .long 4098 # Function type index
- .secrel32 "?foo@@YA_J_J at Z" # Function section relative address
- .secidx "?foo@@YA_J_J at Z" # Function section index
- .byte 0 # Flags
- .asciz "foo" # Function name
- .p2align 2
-Ltmp27:
- .short Ltmp29-Ltmp28 # Record length
-Ltmp28:
- .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
-Ltmp29:
- .short Ltmp31-Ltmp30 # Record length
-Ltmp30:
- .short 4414 # Record kind: S_LOCAL
- .long 19 # TypeIndex
- .short 1 # Flags
- .asciz "x"
- .p2align 2
-Ltmp31:
- .cv_def_range Lfunc_begin1 Lfunc_end1, reg_rel, 30006, 0, 4
- .short 2 # Record length
- .short 4431 # Record kind: S_PROC_ID_END
-Ltmp25:
- .p2align 2
- .cv_linetable 1, "?foo@@YA_J_J at Z", Lfunc_end1
- .section .debug$S,"dr",associative,_main
- .p2align 2
- .long 4 # Debug section magic
- .cv_fpo_data _main
- .long 241 # Symbol subsection for main
- .long Ltmp33-Ltmp32 # Subsection size
-Ltmp32:
- .short Ltmp35-Ltmp34 # Record length
-Ltmp34:
- .short 4423 # Record kind: S_GPROC32_ID
- .long 0 # PtrParent
- .long 0 # PtrEnd
- .long 0 # PtrNext
- .long Lfunc_end2-_main # Code size
- .long 0 # Offset after prologue
- .long 0 # Offset before epilogue
- .long 4103 # Function type index
- .secrel32 _main # Function section relative address
- .secidx _main # Function section index
- .byte 0 # Flags
- .asciz "main" # Function name
- .p2align 2
-Ltmp35:
- .short Ltmp37-Ltmp36 # Record length
-Ltmp36:
- .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
-Ltmp37:
- .short Ltmp39-Ltmp38 # Record length
-Ltmp38:
- .short 4414 # Record kind: S_LOCAL
- .long 116 # TypeIndex
- .short 1 # Flags
- .asciz "argc"
- .p2align 2
-Ltmp39:
- .cv_def_range Lfunc_begin2 Ltmp4, reg_rel, 30006, 0, 4
- .short Ltmp41-Ltmp40 # Record length
-Ltmp40:
- .short 4414 # Record kind: S_LOCAL
- .long 4100 # TypeIndex
- .short 1 # Flags
- .asciz "argv"
- .p2align 2
-Ltmp41:
- .cv_def_range Lfunc_begin2 Ltmp4, reg_rel, 30006, 0, 8
- .short Ltmp43-Ltmp42 # Record length
-Ltmp42:
- .short 4429 # Record kind: S_INLINESITE
- .long 0 # PtrParent
- .long 0 # PtrEnd
- .long 4098 # Inlinee type index
- .cv_inline_linetable 3 1 2 Lfunc_begin2 Lfunc_end2
- .p2align 2
-Ltmp43:
- .short Ltmp45-Ltmp44 # Record length
-Ltmp44:
- .short 4414 # Record kind: S_LOCAL
- .long 19 # TypeIndex
- .short 1 # Flags
- .asciz "x"
- .p2align 2
-Ltmp45:
- .cv_def_range Ltmp3 Ltmp5, subfield_reg, 17, 0
- .cv_def_range Ltmp3 Ltmp5, subfield_reg, 18, 4
- .short 2 # Record length
- .short 4430 # Record kind: S_INLINESITE_END
- .short 2 # Record length
- .short 4431 # Record kind: S_PROC_ID_END
-Ltmp33:
- .p2align 2
- .cv_linetable 2, _main, Lfunc_end2
- .section .debug$S,"dr"
- .cv_filechecksums # File index to string table offset subsection
- .cv_stringtable # String table
- .long 241
- .long Ltmp47-Ltmp46 # Subsection size
-Ltmp46:
- .short Ltmp49-Ltmp48 # Record length
-Ltmp48:
- .short 4428 # Record kind: S_BUILDINFO
- .long 4109 # LF_BUILDINFO index
- .p2align 2
-Ltmp49:
-Ltmp47:
- .p2align 2
- .section .debug$T,"dr"
- .p2align 2
- .long 4 # Debug section magic
- # ArgList (0x1000)
- .short 0xa # Record length
- .short 0x1201 # Record kind: LF_ARGLIST
- .long 0x1 # NumArgs
- .long 0x13 # Argument: __int64
- # Procedure (0x1001)
- .short 0xe # Record length
- .short 0x1008 # Record kind: LF_PROCEDURE
- .long 0x13 # ReturnType: __int64
- .byte 0x0 # CallingConvention: NearC
- .byte 0x0 # FunctionOptions
- .short 0x1 # NumParameters
- .long 0x1000 # ArgListType: (__int64)
- # FuncId (0x1002)
- .short 0xe # Record length
- .short 0x1601 # Record kind: LF_FUNC_ID
- .long 0x0 # ParentScope
- .long 0x1001 # FunctionType: __int64 (__int64)
- .asciz "foo" # Name
- # FuncId (0x1003)
- .short 0xe # Record length
- .short 0x1601 # Record kind: LF_FUNC_ID
- .long 0x0 # ParentScope
- .long 0x1001 # FunctionType: __int64 (__int64)
- .asciz "bar" # Name
- # Pointer (0x1004)
- .short 0xa # Record length
- .short 0x1002 # Record kind: LF_POINTER
- .long 0x470 # PointeeType: char*
- .long 0x800a # Attrs: [ Type: Near32, Mode: Pointer, SizeOf: 4 ]
- # ArgList (0x1005)
- .short 0xe # Record length
- .short 0x1201 # Record kind: LF_ARGLIST
- .long 0x2 # NumArgs
- .long 0x74 # Argument: int
- .long 0x1004 # Argument: char**
- # Procedure (0x1006)
- .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 0x1005 # ArgListType: (int, char**)
- # FuncId (0x1007)
- .short 0x12 # Record length
- .short 0x1601 # Record kind: LF_FUNC_ID
- .long 0x0 # ParentScope
- .long 0x1006 # FunctionType: int (int, char**)
- .asciz "main" # Name
- .byte 243
- .byte 242
- .byte 241
- # StringId (0x1008)
- .short 0xe # Record length
- .short 0x1605 # Record kind: LF_STRING_ID
- .long 0x0 # Id
- .asciz "C:\\src" # StringData
- .byte 241
- # StringId (0x1009)
- .short 0xe # Record length
- .short 0x1605 # Record kind: LF_STRING_ID
- .long 0x0 # Id
- .asciz "a.cpp" # StringData
- .byte 242
- .byte 241
More information about the lldb-commits
mailing list