diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1311,7 +1311,10 @@ // Parse range and line info. uint32_t code_offset = 0; + uint32_t last_line_code_offset = 0; int32_t line_offset = 0; + // Only used for inline range. + int32_t prev_line_offset = -1; bool has_base = false; bool is_new_line_offset = false; @@ -1321,10 +1324,13 @@ auto change_code_offset = [&](uint32_t code_delta) { if (has_base) { - inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( - code_offset, code_delta, decl_line + line_offset)); + uint32_t source_line = + decl_line + (prev_line_offset == -1 ? line_offset : prev_line_offset); + inline_site_sp->ranges.Append( + RangeSourceLineVector::Entry(code_offset, code_delta, source_line)); is_prologue_end = false; is_start_of_statement = false; + prev_line_offset = -1; } else { is_start_of_statement = true; } @@ -1337,25 +1343,35 @@ true, false, is_prologue_end, false, false); inline_site_sp->line_entries.push_back(line_entry); is_new_line_offset = false; + last_line_code_offset = code_offset; } }; auto change_code_length = [&](uint32_t length) { - inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( - code_offset, length, decl_line + line_offset)); - has_base = false; - + uint32_t source_line = + decl_line + (prev_line_offset == -1 ? line_offset : prev_line_offset); + inline_site_sp->ranges.Append( + RangeSourceLineVector::Entry(code_offset, length, source_line)); LineTable::Entry end_line_entry(func_base + code_offset + length, - decl_line + line_offset, 0, decl_file_idx, - false, false, false, false, true); + source_line, 0, decl_file_idx, false, false, + false, false, true); inline_site_sp->line_entries.push_back(end_line_entry); + has_base = false; + prev_line_offset = -1; }; auto change_line_offset = [&](int32_t line_delta) { line_offset += line_delta; if (has_base) { - LineTable::Entry line_entry( - func_base + code_offset, decl_line + line_offset, 0, decl_file_idx, - is_start_of_statement, false, is_prologue_end, false, false); - inline_site_sp->line_entries.push_back(line_entry); + if (last_line_code_offset == code_offset) { + prev_line_offset = line_offset - line_delta; + // Add line entry in next call to change_code_offset. + is_new_line_offset = true; + } else { + LineTable::Entry line_entry( + func_base + code_offset, decl_line + line_offset, 0, decl_file_idx, + is_start_of_statement, false, is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + last_line_code_offset = code_offset; + } } else { // Add line entry in next call to change_code_offset. is_new_line_offset = true; diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites_live.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites_live.lldbinit --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites_live.lldbinit +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites_live.lldbinit @@ -1,3 +1,4 @@ +image dump line-table inline_sites_live.cpp -v br set -p BP_bar -f inline_sites_live.cpp br set -p BP_foo -f inline_sites_live.cpp run diff --git a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp --- a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp @@ -1,7 +1,9 @@ // clang-format off // REQUIRES: system-windows -// RUN: %build -o %t.exe -- %s +// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s +// RUN: lld-link -debug:full %t.obj -base:0x400000 -out:%t.exe -pdb:%t.pdb + // RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \ // RUN: %p/Inputs/inline_sites_live.lldbinit 2>&1 | FileCheck %s @@ -22,6 +24,32 @@ foo(argc); } +// CHECK: (lldb) image dump line-table inline_sites_live.cpp -v +// CHECK-NEXT: Line table +// CHECK-NEXT: {{.*}}401000:{{.*}}:10 +// CHECK-NEXT: {{.*}}401007:{{.*}}:10, is_terminal_entry = TRUE +// CHECK-NEXT: {{.*}}401010:{{.*}}:12 +// CHECK-NEXT: {{.*}}401018:{{.*}}:13 +// CHECK-NEXT: {{.*}}401021:{{.*}}:14 +// CHECK-NEXT: {{.*}}401027:{{.*}}:14, is_terminal_entry = TRUE +// CHECK-NEXT: {{.*}}401030:{{.*}}:16 +// CHECK-NEXT: {{.*}}401038:{{.*}}:17 +// CHECK-NEXT: {{.*}}401043:{{.*}}:18 +// CHECK-NEXT: {{.*}}40104b:{{.*}}:13, is_start_of_statement = TRUE, is_prologue_end = TRUE +// CHECK-NEXT: {{.*}}401054:{{.*}}:19 +// CHECK-NEXT: {{.*}}40105d:{{.*}}:20 +// CHECK-NEXT: {{.*}}401066:{{.*}}:21 +// CHECK-NEXT: {{.*}}40106c:{{.*}}:21, is_terminal_entry = TRUE +// CHECK-NEXT: {{.*}}401070:{{.*}}:23 +// CHECK-NEXT: {{.*}}40107d:{{.*}}:24 +// CHECK-NEXT: {{.*}}401085:{{.*}}:17, is_start_of_statement = TRUE, is_prologue_end = TRUE +// CHECK-NEXT: {{.*}}401090:{{.*}}:18 +// CHECK-NEXT: {{.*}}401098:{{.*}}:13, is_start_of_statement = TRUE, is_prologue_end = TRUE +// CHECK-NEXT: {{.*}}4010a1:{{.*}}:19, is_start_of_statement = TRUE +// CHECK-NEXT: {{.*}}4010aa:{{.*}}:20 +// CHECK-NEXT: {{.*}}4010b3:{{.*}}:25 +// CHECK-NEXT: {{.*}}4010ba:{{.*}}:25, is_terminal_entry = TRUE + // CHECK: * thread #1, stop reason = breakpoint 1 // CHECK-NEXT: frame #0: {{.*}}`main [inlined] bar(param=2) // CHECK: (lldb) p param