Skip to content

Commit a2c9146

Browse files
authored
[lldb][NativePDB] Handle S_DEFRANGE_REGISTER_REL_INDIR (llvm#190336)
Since llvm#189401, LLVM and Clang generate `S_DEFRANGE_REGISTER_REL_INDIR` for indirect locations. This adds support in LLDB. The offset added after dereferencing is signed here - unlike in `S_REGREL32_INDIR` (at least that's the assumption). So I updated `MakeRegisterBasedIndirectLocationExpressionInternal` to handle the signedness. This is the reason the MSVC test was changed here. I didn't find a test case where LLVM emits the record with the `VFRAME` register. Other than that, the clang test is similar to the MSVC one except that the locations are slightly different.
1 parent fecf609 commit a2c9146

File tree

5 files changed

+109
-3
lines changed

5 files changed

+109
-3
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,9 @@ static bool MakeRegisterBasedIndirectLocationExpressionInternal(
166166
return false;
167167

168168
stream.PutHex8(llvm::dwarf::DW_OP_deref);
169-
stream.PutHex8(llvm::dwarf::DW_OP_plus_uconst);
169+
stream.PutHex8(llvm::dwarf::DW_OP_consts);
170170
stream.PutSLEB128(offset);
171+
stream.PutHex8(llvm::dwarf::DW_OP_plus);
171172

172173
return true;
173174
}
@@ -229,6 +230,31 @@ DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(
229230
});
230231
}
231232

233+
DWARFExpression lldb_private::npdb::MakeVFrameRelIndirLocationExpression(
234+
llvm::StringRef fpo_program, int32_t offset, int32_t offset_in_udt,
235+
lldb::ModuleSP module) {
236+
return MakeLocationExpressionInternal(
237+
module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
238+
const ArchSpec &architecture = module->GetArchitecture();
239+
240+
if (!EmitVFrameEvaluationDWARFExpression(
241+
fpo_program, architecture.GetMachine(), stream))
242+
return false;
243+
244+
stream.PutHex8(llvm::dwarf::DW_OP_consts);
245+
stream.PutSLEB128(offset);
246+
stream.PutHex8(llvm::dwarf::DW_OP_plus);
247+
stream.PutHex8(llvm::dwarf::DW_OP_deref);
248+
stream.PutHex8(llvm::dwarf::DW_OP_consts);
249+
stream.PutSLEB128(offset_in_udt);
250+
stream.PutHex8(llvm::dwarf::DW_OP_plus);
251+
252+
register_kind = eRegisterKindLLDB;
253+
254+
return true;
255+
});
256+
}
257+
232258
DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
233259
uint16_t section, uint32_t offset, ModuleSP module) {
234260
assert(section > 0);

lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ MakeRegRelIndirLocationExpression(llvm::codeview::RegisterId reg,
4747
DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program,
4848
int32_t offset,
4949
lldb::ModuleSP module);
50+
DWARFExpression
51+
MakeVFrameRelIndirLocationExpression(llvm::StringRef fpo_program,
52+
int32_t offset, int32_t offset_in_udt,
53+
lldb::ModuleSP module);
5054
DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset,
5155
lldb::ModuleSP module);
5256
llvm::Expected<DWARFExpression> MakeConstantLocationExpression(

lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,37 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
888888
AddDwarfRange(location_map, expr, raw_ranges);
889889
break;
890890
}
891+
case S_DEFRANGE_REGISTER_REL_INDIR: {
892+
DefRangeRegisterRelIndirSym loc(
893+
SymbolRecordKind::DefRangeRegisterRelIndirSym);
894+
if (llvm::Error error =
895+
SymbolDeserializer::deserializeAs<DefRangeRegisterRelIndirSym>(
896+
loc_specifier_cvs, loc)) {
897+
llvm::consumeError(std::move(error));
898+
return result;
899+
}
900+
Variable::RangeList raw_ranges =
901+
MakeRangeList(index, loc.Range, loc.Gaps);
902+
RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
903+
DWARFExpression expr;
904+
if (reg_id == RegisterId::VFRAME) {
905+
llvm::StringRef program;
906+
if (GetFrameDataProgram(index, raw_ranges, program))
907+
expr = MakeVFrameRelIndirLocationExpression(
908+
program, loc.Hdr.BasePointerOffset, loc.Hdr.OffsetInUdt,
909+
module);
910+
else {
911+
// invalid variable
912+
}
913+
} else {
914+
expr = MakeRegRelIndirLocationExpression(
915+
reg_id, loc.Hdr.BasePointerOffset, loc.Hdr.OffsetInUdt, module);
916+
}
917+
// FIXME: If it's UDT, we need to know the size of the value in byte.
918+
if (!loc.hasSpilledUDTMember())
919+
AddDwarfRange(location_map, expr, raw_ranges);
920+
break;
921+
}
891922
case S_DEFRANGE_SUBFIELD_REGISTER: {
892923
DefRangeSubfieldRegisterSym loc(
893924
SymbolRecordKind::DefRangeSubfieldRegisterSym);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# REQUIRES: lld, target-windows
2+
3+
# Test that LLDB can show variables introduced in C++ 17 structured bindings
4+
# when compiled with clang-cl.
5+
6+
# RUN: split-file %s %t
7+
8+
# RUN: %build --compiler=clang-cl --arch=64 --std=c++17 --nodefaultlib -o %t.exe -- %t/main.cpp
9+
# RUN: lldb-test symbols %t.exe | FileCheck %s --check-prefix=SYMBOLS
10+
# RUN: %lldb -f %t.exe -s %t/commands.input | FileCheck %s --check-prefix=LLDB
11+
12+
#--- main.cpp
13+
14+
struct Foo { int a; int b; };
15+
16+
int main() {
17+
Foo f{1, 2};
18+
19+
auto&[a, b] = f;
20+
return a + b; // break here
21+
}
22+
23+
#--- commands.input
24+
25+
br set -p "break here"
26+
r
27+
v f
28+
v a
29+
v b
30+
q
31+
32+
# SYMBOLS: Function{{.*}}, demangled = main, type =
33+
# SYMBOLS-NEXT: Block{{.*}}, ranges =
34+
# SYMBOLS-DAG: Variable{{.*}}, name = "f", type = {{.*}} (Foo), scope = local, location =
35+
# SYMBOLS-DAG: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = 0x00000000:
36+
# SYMBOLS-NEXT: [{{.*}}): DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts +0, DW_OP_plus
37+
# SYMBOLS-DAG: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = 0x00000000:
38+
# SYMBOLS-NEXT: [{{.*}}): DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts {{[+-][0-9]+}}, DW_OP_plus
39+
40+
# LLDB: (lldb) v f
41+
# LLDB-NEXT: (Foo) f = (a = 1, b = 2)
42+
# LLDB-NEXT: (lldb) v a
43+
# LLDB-NEXT: (int) a = 1
44+
# LLDB-NEXT: (lldb) v b
45+
# LLDB-NEXT: (int) b = 2

lldb/test/Shell/SymbolFile/NativePDB/structured-bindings-msvc.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ q
3232
# SYMBOLS: Function{{.*}}, demangled = main, type =
3333
# SYMBOLS-NEXT: Block{{.*}}, ranges =
3434
# SYMBOLS-NEXT: Variable{{.*}}, name = "f", type = {{.*}} (Foo), scope = local, location =
35-
# SYMBOLS-NEXT: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_plus_uconst 0x{{[0-9]+}}
36-
# SYMBOLS-NEXT: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_plus_uconst 0x0
35+
# SYMBOLS-NEXT: Variable{{.*}}, name = "b", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts {{[+-][0-9]+}}, DW_OP_plus
36+
# SYMBOLS-NEXT: Variable{{.*}}, name = "a", type = {{.*}} (int), scope = local, location = DW_OP_breg{{.*}}, DW_OP_deref, DW_OP_consts +0, DW_OP_plus
3737

3838
# LLDB: (lldb) v f
3939
# LLDB-NEXT: (Foo) f = (a = 1, b = 2)

0 commit comments

Comments
 (0)