[Lldb-commits] [lldb] [lldb][MSABI] Take offset of vbptr into account (PR #190679)

via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 6 13:44:37 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Nerixyz (Nerixyz)

<details>
<summary>Changes</summary>

In the MS ABI, the offset found in the virtual base table is relative to the virtual base pointer. See Clang's `MicrosoftCXXABI::emitVBTableDefinition`: https://github.com/llvm/llvm-project/blob/1a0ca1019d214a24b55a45704dc71fa183672362/clang/lib/CodeGen/MicrosoftCXXABI.cpp#L2247-L2261

We previously assumed the offset was relative to the record's start.

For example for `B` in
```cpp
struct Extra {
  int e1 = 1;
};
struct A {
  int a = 3;
};
struct B : public Extra, public virtual A {
  int b = 4;
};
```
the `vbptr` is at offset 8 and inside that table, the offset for `A` is 16 while `A` sits at offset 24 from `B`'s start:
```
> cl main.cpp /GS- /Z7 /nologo /d1reportSingleClassLayoutB
(...)
class B size(32):
        +---
 0      | +--- (base class Extra)
 0      | | e1
        | +---
 8      | {vbptr}
16      | b
        | <alignment member> (size=4)
        | <alignment member> (size=4)
        +---
        +--- (virtual base A)
24      | a
        +---

B::$vbtable@:
 0      | -8
 1      | 16 (Bd(B+8)A)   (<- value we read)
```

---
Full diff: https://github.com/llvm/llvm-project/pull/190679.diff


3 Files Affected:

- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+2) 
- (modified) lldb/test/API/lang/cpp/diamond/TestCppDiamond.py (+31) 
- (modified) lldb/test/API/lang/cpp/diamond/main.cpp (+9) 


``````````diff
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index fba6aec296324..12fb975822932 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -313,6 +313,8 @@ static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx,
   if (base_offset == INT64_MAX)
     return false;
 
+  if (vtable_ctx.isMicrosoft())
+    base_offset += record_layout.getVBPtrOffset().getQuantity();
   bit_offset = base_offset * 8;
 
   return true;
diff --git a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
index 27062c0666a1a..edb60922934de 100644
--- a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
+++ b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
@@ -107,6 +107,37 @@ def test(self):
         # Use variable paths to access the members.
         self.expect_var_path("j1.x", type="long", value="1")
 
+        children = [
+            ValueCheck(
+                type="Extra",
+                children=[
+                    ValueCheck(
+                        type="short",
+                        name="some_value",
+                        value="3",
+                    )
+                ],
+            ),
+            ValueCheck(
+                type="VBase",
+                children=[ValueCheck(type="int", name="m_value", value="12347")],
+            ),
+            ValueCheck(
+                type="Derived1",
+                children=[
+                    ValueCheck(
+                        type="VBase",
+                        children=[
+                            ValueCheck(type="int", name="m_value", value="12347")
+                        ],
+                    )
+                ],
+            ),
+            ValueCheck(type="long", name="z", value="4"),
+        ]
+        # Test that the virtual bases are correct when v(b)table pointer is offset.
+        self.expect_expr("j3", result_type="Joiner3", result_children=children)
+
     @expectedFailureAll
     @no_debug_info_test
     def test_invalid_member(self):
diff --git a/lldb/test/API/lang/cpp/diamond/main.cpp b/lldb/test/API/lang/cpp/diamond/main.cpp
index fdf2f3d326747..b9546e7a52c9b 100644
--- a/lldb/test/API/lang/cpp/diamond/main.cpp
+++ b/lldb/test/API/lang/cpp/diamond/main.cpp
@@ -20,9 +20,18 @@ struct Joiner2 : public Derived2 {
   long y = 2;
 };
 
+struct Extra {
+  short some_value = 3;
+};
+
+struct Joiner3 : public Extra, public virtual VBase, public Derived1 {
+  long z = 4;
+};
+
 int main(int argc, const char *argv[]) {
   Joiner1 j1;
   Joiner2 j2;
+  Joiner3 j3;
   Derived2 *d = &j1;
   d = &j2;  // breakpoint 1
   return 0; // breakpoint 2

``````````

</details>


https://github.com/llvm/llvm-project/pull/190679


More information about the lldb-commits mailing list