diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp index 1019f825577e..b0333079812a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp @@ -166,8 +166,9 @@ static bool MakeRegisterBasedIndirectLocationExpressionInternal( return false; stream.PutHex8(llvm::dwarf::DW_OP_deref); - stream.PutHex8(llvm::dwarf::DW_OP_plus_uconst); + stream.PutHex8(llvm::dwarf::DW_OP_consts); stream.PutSLEB128(offset); + stream.PutHex8(llvm::dwarf::DW_OP_plus); return true; } @@ -229,6 +230,31 @@ DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression( }); } +DWARFExpression lldb_private::npdb::MakeVFrameRelIndirLocationExpression( + llvm::StringRef fpo_program, int32_t offset, int32_t offset_in_udt, + lldb::ModuleSP module) { + return MakeLocationExpressionInternal( + module, [&](Stream &stream, RegisterKind ®ister_kind) -> bool { + const ArchSpec &architecture = module->GetArchitecture(); + + if (!EmitVFrameEvaluationDWARFExpression( + fpo_program, architecture.GetMachine(), stream)) + return false; + + stream.PutHex8(llvm::dwarf::DW_OP_consts); + stream.PutSLEB128(offset); + stream.PutHex8(llvm::dwarf::DW_OP_plus); + stream.PutHex8(llvm::dwarf::DW_OP_deref); + stream.PutHex8(llvm::dwarf::DW_OP_consts); + stream.PutSLEB128(offset_in_udt); + stream.PutHex8(llvm::dwarf::DW_OP_plus); + + register_kind = eRegisterKindLLDB; + + return true; + }); +} + DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression( uint16_t section, uint32_t offset, ModuleSP module) { assert(section > 0); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h index 81a47d6dad0f..e1478db6ce9f 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h @@ -47,6 +47,10 @@ MakeRegRelIndirLocationExpression(llvm::codeview::RegisterId reg, DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module); +DWARFExpression +MakeVFrameRelIndirLocationExpression(llvm::StringRef fpo_program, + int32_t offset, int32_t offset_in_udt, + lldb::ModuleSP module); DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset, lldb::ModuleSP module); llvm::Expected MakeConstantLocationExpression( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index a90ca32fffac..5860d90eca68 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -888,6 +888,37 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( AddDwarfRange(location_map, expr, raw_ranges); break; } + case S_DEFRANGE_REGISTER_REL_INDIR: { + DefRangeRegisterRelIndirSym loc( + SymbolRecordKind::DefRangeRegisterRelIndirSym); + if (llvm::Error error = + SymbolDeserializer::deserializeAs( + loc_specifier_cvs, loc)) { + llvm::consumeError(std::move(error)); + return result; + } + 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 = MakeVFrameRelIndirLocationExpression( + program, loc.Hdr.BasePointerOffset, loc.Hdr.OffsetInUdt, + module); + else { + // invalid variable + } + } else { + expr = MakeRegRelIndirLocationExpression( + reg_id, loc.Hdr.BasePointerOffset, loc.Hdr.OffsetInUdt, 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; + } case S_DEFRANGE_SUBFIELD_REGISTER: { DefRangeSubfieldRegisterSym loc( SymbolRecordKind::DefRangeSubfieldRegisterSym); diff --git a/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-clang.test b/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-clang.test new file mode 100644 index 000000000000..254015ff198f --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-clang.test @@ -0,0 +1,45 @@ +# REQUIRES: lld, target-windows + +# Test that LLDB can show variables introduced in C++ 17 structured bindings +# when compiled with clang-cl. + +# RUN: split-file %s %t + +# RUN: %build --compiler=clang-cl --arch=64 --std=c++17 --nodefaultlib -o %t.exe -- %t/main.cpp +# RUN: lldb-test symbols %t.exe | FileCheck %s --check-prefix=SYMBOLS +# RUN: %lldb -f %t.exe -s %t/commands.input | FileCheck %s --check-prefix=LLDB + +#--- main.cpp + +struct Foo { int a; int b; }; + +int main() { + Foo f{1, 2}; + + auto&[a, b] = f; + return a + b; // break here +} + +#--- commands.input + +br set -p "break here" +r +v f +v a +v b +q + +# SYMBOLS: Function{{.*}}, demangled = main, type = +# SYMBOLS-NEXT: Block{{.*}}, ranges = +# SYMBOLS-DAG: Variable{{.*}}, name = "f", type = {{.*}} (Foo), scope = local, location = +# SYMBOLS-DAG: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = 0x00000000: +# SYMBOLS-NEXT: [{{.*}}): DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts +0, DW_OP_plus +# SYMBOLS-DAG: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = 0x00000000: +# SYMBOLS-NEXT: [{{.*}}): DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts {{[+-][0-9]+}}, DW_OP_plus + +# LLDB: (lldb) v f +# LLDB-NEXT: (Foo) f = (a = 1, b = 2) +# LLDB-NEXT: (lldb) v a +# LLDB-NEXT: (int) a = 1 +# LLDB-NEXT: (lldb) v b +# LLDB-NEXT: (int) b = 2 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-msvc.test b/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-msvc.test index ebe6cceda7ea..a4d162248e6d 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-msvc.test +++ b/lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-msvc.test @@ -32,8 +32,8 @@ q # SYMBOLS: Function{{.*}}, demangled = main, type = # SYMBOLS-NEXT: Block{{.*}}, ranges = # SYMBOLS-NEXT: Variable{{.*}}, name = "f", type = {{.*}} (Foo), scope = local, location = -# SYMBOLS-NEXT: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_plus_uconst 0x{{[0-9]+}} -# SYMBOLS-NEXT: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_plus_uconst 0x0 +# SYMBOLS-NEXT: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts {{[+-][0-9]+}}, DW_OP_plus +# SYMBOLS-NEXT: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts +0, DW_OP_plus # LLDB: (lldb) v f # LLDB-NEXT: (Foo) f = (a = 1, b = 2)