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 @@ -1303,8 +1303,8 @@ GetFileIndex(*cii, inlinee_line.Header->FileID); if (!file_index_or_err) return; - uint32_t decl_file_idx = file_index_or_err.get(); - decl_file = files.GetFileSpecAtIndex(decl_file_idx); + uint32_t file_offset = file_index_or_err.get(); + decl_file = files.GetFileSpecAtIndex(file_offset); uint32_t decl_line = inlinee_line.Header->SourceLineNum; std::unique_ptr decl_up = std::make_unique(decl_file, decl_line); @@ -1312,54 +1312,36 @@ // Parse range and line info. uint32_t code_offset = 0; int32_t line_offset = 0; - bool has_base = false; - bool is_new_line_offset = false; - - bool is_start_of_statement = false; + llvm::Optional code_offset_base; + llvm::Optional code_offset_end; + llvm::Optional cur_line_offset; + llvm::Optional next_line_offset; + llvm::Optional next_file_offset; + + bool is_terminal_entry = false; + bool is_start_of_statement = true; // The first instruction is the prologue end. bool is_prologue_end = true; - 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)); - is_prologue_end = false; - is_start_of_statement = false; - } else { - is_start_of_statement = true; - } - has_base = true; - code_offset += code_delta; - - if (is_new_line_offset) { - LineTable::Entry line_entry(func_base + code_offset, - decl_line + line_offset, 0, decl_file_idx, - true, false, is_prologue_end, false, false); - inline_site_sp->line_entries.push_back(line_entry); - is_new_line_offset = false; - } - }; - auto change_code_length = [&](uint32_t length) { - inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( - code_offset, length, decl_line + line_offset)); - has_base = false; - - LineTable::Entry end_line_entry(func_base + code_offset + length, - decl_line + line_offset, 0, decl_file_idx, - false, false, false, false, true); - inline_site_sp->line_entries.push_back(end_line_entry); + auto update_code_offset = [&](uint32_t code_delta) { + if (!code_offset_base) + code_offset_base = code_offset; + else if (!code_offset_end) + code_offset_end = *code_offset_base + code_delta; }; - auto change_line_offset = [&](int32_t line_delta) { + auto update_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); - } else { - // Add line entry in next call to change_code_offset. - is_new_line_offset = true; - } + if (!code_offset_base || !cur_line_offset) + cur_line_offset = line_offset; + else + next_line_offset = line_offset; + ; + }; + auto update_file_offset = [&](uint32_t offset) { + if (!code_offset_base) + file_offset = offset; + else + next_file_offset = offset; }; for (auto &annot : inline_site.annotations()) { @@ -1367,26 +1349,67 @@ case BinaryAnnotationsOpCode::CodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: - change_code_offset(annot.U1); + code_offset += annot.U1; + update_code_offset(annot.U1); break; case BinaryAnnotationsOpCode::ChangeLineOffset: - change_line_offset(annot.S1); + update_line_offset(annot.S1); break; case BinaryAnnotationsOpCode::ChangeCodeLength: - change_code_length(annot.U1); + update_code_offset(annot.U1); code_offset += annot.U1; + is_terminal_entry = true; break; case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: - change_code_offset(annot.U1); - change_line_offset(annot.S1); + code_offset += annot.U1; + update_code_offset(annot.U1); + update_line_offset(annot.S1); break; case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: - change_code_offset(annot.U2); - change_code_length(annot.U1); + code_offset += annot.U2; + update_code_offset(annot.U2); + update_code_offset(annot.U1); + code_offset += annot.U1; + is_terminal_entry = true; + break; + case BinaryAnnotationsOpCode::ChangeFile: + update_file_offset(annot.U1); break; default: break; } + + // Add range if current range is finished. + if (code_offset_base && code_offset_end && cur_line_offset) { + inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( + *code_offset_base, *code_offset_end - *code_offset_base, + decl_line + *cur_line_offset)); + // Set base, end, file offset and line offset for next range. + if (next_file_offset) + file_offset = *next_file_offset; + cur_line_offset = next_line_offset ? next_line_offset : llvm::None; + code_offset_base = is_terminal_entry ? llvm::None : code_offset_end; + code_offset_end = next_line_offset = next_file_offset = llvm::None; + } + if (code_offset_base && cur_line_offset) { + if (is_terminal_entry) { + LineTable::Entry line_entry( + func_base + *code_offset_base, decl_line + *cur_line_offset, 0, + file_offset, false, false, false, false, true); + inline_site_sp->line_entries.push_back(line_entry); + } else { + LineTable::Entry line_entry(func_base + *code_offset_base, + decl_line + *cur_line_offset, 0, + file_offset, is_start_of_statement, false, + is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + is_prologue_end = false; + is_start_of_statement = false; + } + } + if (is_terminal_entry) + is_start_of_statement = true; + is_terminal_entry = false; } inline_site_sp->ranges.Sort(); diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.lldbinit --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.lldbinit +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.lldbinit @@ -13,7 +13,6 @@ b c.h:7 b a.cpp:3 b a.cpp:4 -b a.h:8 image lookup -a 0x140001003 -v image lookup -a 0x140001004 -v diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.s b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.s --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.s +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.s @@ -116,6 +116,8 @@ mov dword ptr [rsp + 48], eax .cv_loc 0 1 4 0 # a.cpp:4:0 xor eax, eax + # Use fake debug info to tests inline info. + .cv_loc 1 2 20 0 add rsp, 56 ret .Ltmp7: diff --git a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test --- a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test +++ b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test @@ -21,7 +21,8 @@ # CHECK-NEXT: 0x0000000140001035: /tmp/c.h:7 # CHECK-NEXT: 0x0000000140001039: /tmp/a.cpp:3 # CHECK-NEXT: 0x000000014000103d: /tmp/a.cpp:4 -# CHECK-NEXT: 0x0000000140001044: /tmp/a.h:8, is_start_of_statement = TRUE +# CHECK-NEXT: 0x000000014000103f: /tmp/a.h:20 +# CHECK-NEXT: 0x0000000140001044: /tmp/a.h:8 # CHECK-NEXT: 0x0000000140001046: /tmp/a.cpp:4, is_terminal_entry = TRUE #CHECK: (lldb) b a.h:5 @@ -31,7 +32,7 @@ #CHECK: (lldb) b a.h:7 #CHECK: Breakpoint 3: where = {{.*}}`main + 16 [inlined] Namespace1::foo + 12 at a.h:7, address = 0x0000000140001010 #CHECK: (lldb) b a.h:8 -#CHECK: Breakpoint 4: where = {{.*}}`main + 68 [inlined] Namespace1::foo at a.h:8, address = 0x0000000140001044 +#CHECK: Breakpoint 4: where = {{.*}}`main + 68 [inlined] Namespace1::foo + 5 at a.h:8, address = 0x0000000140001044 #CHECK: (lldb) b a.h:9 #CHECK: Breakpoint 5: where = {{.*}}`main + 24 [inlined] Namespace1::foo + 20 at a.h:9, address = 0x0000000140001018 #CHECK: (lldb) b b.h:5 @@ -50,8 +51,6 @@ #CHECK: Breakpoint 12: where = {{.*}}`main + 57 at a.cpp:3, address = 0x0000000140001039 #CHECK: (lldb) b a.cpp:4 #CHECK: Breakpoint 13: where = {{.*}}`main + 61 at a.cpp:4, address = 0x000000014000103d -#CHECK: (lldb) b a.h:8 -#CHECK: Breakpoint 14: where = {{.*}}`main + 68 [inlined] Namespace1::foo at a.h:8, address = 0x0000000140001044 # CEHCK-LABEL: (lldb) image lookup -a 0x140001003 -v # CHECK: Summary: {{.*}}`main + 3 at a.cpp:2 @@ -66,7 +65,7 @@ # CHECK-NEXT: {{.*}}`main + 4 at a.cpp:3 # CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046) # CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046) -# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x140001044-0x140001046), name = "Namespace1::foo", decl = a.h:4 +# 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) @@ -78,7 +77,7 @@ # CHECK-NEXT: {{.*}}`main + 4 at a.cpp:3 # CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046) # CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046) -# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x140001044-0x140001046), name = "Namespace1::foo", decl = a.h:4 +# 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) @@ -91,7 +90,7 @@ # CHECK-NEXT: {{.*}}`main + 4 at a.cpp:3 # CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046) # CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046) -# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x140001044-0x140001046), name = "Namespace1::foo", decl = a.h:4 +# 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) @@ -108,7 +107,7 @@ # CHECK-NEXT: {{.*}}`main + 4 at a.cpp:3 # CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046) # CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046) -# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x140001044-0x140001046), name = "Namespace1::foo", decl = a.h:4 +# 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-NEXT: id = {{.*}}, range = [0x14000102a-0x140001039), name = "Namespace2::Class2::func", decl = c.h:4 # CHECK: LineEntry: [0x000000014000102a-0x0000000140001031): /tmp/c.h:5 @@ -129,11 +128,11 @@ # CHECK-NEXT: Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046) # CEHCK-LABEL: (lldb) image lookup -a 0x140001044 -v -# CHECK: Summary: {{.*}}`main + 68 [inlined] Namespace1::foo at a.h:8 -# CHECK-NEXT: {{.*}}`main + 68 at a.cpp:3 +# CHECK: Summary: {{.*}}`main + 68 [inlined] Namespace1::foo + 5 at a.h:8 +# CHECK-NEXT: {{.*}}`main + 63 at a.cpp:3 # CHECK: Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046) # CHECK: Blocks: id = {{.*}}, range = [0x140001000-0x140001046) -# CHECK-NEXT: id = {{.*}}, ranges = [0x140001004-0x140001039)[0x140001044-0x140001046), name = "Namespace1::foo", decl = a.h:4 +# 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)