[LLDB][NativePDB] Fix inline line info in line table
authorZequan Wu <zequanwu@google.com>
Thu, 14 Apr 2022 17:58:17 +0000 (10:58 -0700)
committerZequan Wu <zequanwu@google.com>
Thu, 14 Apr 2022 18:00:56 +0000 (11:00 -0700)
It fixes the following case:
```
0602      line 1 (+1)
0315      code 0x15 (+0x15)
0B2B      code 0x20 (+0xB) line 2 (+1)
0602      line 3 (+1)
0311      code 0x31 (+0x11)
...
```

Inline ranges should have following mapping:
`[0x15, 0x20) -> line 1`
`[0x20, 0x31) -> line 2`
Inline line entries:
`0x15, line 1`, `0x20, line 2`, `0x31, line 3`.

Reviewed By: labath

Differential Revision: https://reviews.llvm.org/D123092

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.lldbinit
lldb/test/Shell/SymbolFile/NativePDB/Inputs/inline_sites.s
lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test

index 351c0bf..00d4422 100644 (file)
@@ -1303,8 +1303,8 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
       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<Declaration> decl_up =
       std::make_unique<Declaration>(decl_file, decl_line);
@@ -1312,54 +1312,36 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
   // 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<uint32_t> code_offset_base;
+  llvm::Optional<uint32_t> code_offset_end;
+  llvm::Optional<uint32_t> cur_line_offset;
+  llvm::Optional<uint32_t> next_line_offset;
+  llvm::Optional<uint32_t> 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 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
     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();
index f30abbb..90a0054 100644 (file)
@@ -13,7 +13,6 @@ b c.h: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
index 055c9b7..aac8f4c 100644 (file)
@@ -116,6 +116,8 @@ main:                                   # @main
        mov     dword ptr [rsp + 48], eax\r
        .cv_loc 0 1 4 0                         # a.cpp:4:0\r
        xor     eax, eax\r
+       # Use fake debug info to tests inline info.\r
+       .cv_loc 1 2 20 0\r
        add     rsp, 56\r
        ret\r
 .Ltmp7:\r
index a9b748d..70e344e 100644 (file)
@@ -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)
 # 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
 # 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)