https://github.com/Nerixyz created 
https://github.com/llvm/llvm-project/pull/214960

In the Microsoft ABI, the offset to a virtual base we read from the v(b)table 
is relative to the vbptr (pointer to vbtable). Unlike on Itanium, where the 
offset is relative to the start of the record. This makes a difference when the 
virtual base isn't the first one. Because then the `vbptr` is offset.

For example in the test I added, the record layout for `UserUser` looks like 
this (https://godbolt.org/z/TYnMW5hcs):
```
class UserUser  size(48):
        +---
 0      | +--- (base class Padding4)
 0      | | member
        | +---
 8      | +--- (base class User)
 8      | | +--- (base class Padding3)
 8      | | | member
        | | +---
16      | | {vbptr}
24      | | member
        | | <alignment member> (size=6)
        | | <alignment member> (size=4)
        | +---
32      | +--- (base class Padding5)
32      | | member
        | +---
34      | member
        | <alignment member> (size=4)
        | <alignment member> (size=4)
        +---
        +--- (virtual base VBase1)
40      | member
        +---
        +--- (virtual base VBase2)
42      | member
        +---

UserUser::$vbtable@:
 0      | -8
 1      | 24 (UserUserd(User+8)VBase1)
 2      | 26 (UserUserd(User+8)VBase2)
```

When trying to read the virtual base in `User`, we'd read the `vbtable` at 
offset 1 and get 24 as the offset (-> 16 + 24 = 40).

In our tests, the virtual base was always the first one, so this never showed 
up.

>From d92087117ad8322327f5cfcf3e10ecfa61266f28 Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Sat, 8 Aug 2026 13:50:28 +0200
Subject: [PATCH] [lldb] Read virtual bases relative to vbptr on MS ABI

---
 .../TypeSystem/Clang/TypeSystemClang.cpp      |  4 ++
 lldb/test/API/lang/cpp/virtual-bases/Makefile |  3 ++
 .../cpp/virtual-bases/TestCppVirtualBases.py  | 49 +++++++++++++++++++
 lldb/test/API/lang/cpp/virtual-bases/main.cpp | 30 ++++++++++++
 4 files changed, 86 insertions(+)
 create mode 100644 lldb/test/API/lang/cpp/virtual-bases/Makefile
 create mode 100644 lldb/test/API/lang/cpp/virtual-bases/TestCppVirtualBases.py
 create mode 100644 lldb/test/API/lang/cpp/virtual-bases/main.cpp

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 4a637f0817759..806042e009059 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -313,6 +313,10 @@ static bool GetVBaseBitOffset(VTableContextBase 
&vtable_ctx,
   if (base_offset == INT64_MAX)
     return false;
 
+  // In the Microsoft ABI, the offset we read in the vtable is relative to the
+  // vbptr in the type itself, not relative to the start of the record.
+  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/virtual-bases/Makefile 
b/lldb/test/API/lang/cpp/virtual-bases/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/virtual-bases/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/virtual-bases/TestCppVirtualBases.py 
b/lldb/test/API/lang/cpp/virtual-bases/TestCppVirtualBases.py
new file mode 100644
index 0000000000000..141dd0321bb77
--- /dev/null
+++ b/lldb/test/API/lang/cpp/virtual-bases/TestCppVirtualBases.py
@@ -0,0 +1,49 @@
+"""
+Test reading virtual bases through the vtable.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class TestCppVirtualBases(TestBase):
+    @no_debug_info_test
+    def test(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+
+        children = [
+            ValueCheck(
+                type="Padding4",
+                children=[ValueCheck(type="short", name="member", value="4")],
+            ),
+            ValueCheck(
+                type="User",
+                children=[
+                    ValueCheck(
+                        type="Padding3",
+                        children=[ValueCheck(type="short", name="member", 
value="3")],
+                    ),
+                    ValueCheck(
+                        type="VBase1",
+                        children=[ValueCheck(type="short", name="member", 
value="1")],
+                    ),
+                    ValueCheck(
+                        type="VBase2",
+                        children=[ValueCheck(type="short", name="member", 
value="2")],
+                    ),
+                    ValueCheck(type="short", name="member", value="6"),
+                ],
+            ),
+            ValueCheck(
+                type="Padding5",
+                children=[ValueCheck(type="short", name="member", value="5")],
+            ),
+            ValueCheck(type="short", name="member", value="7"),
+        ]
+        self.expect_expr("useruser", result_type="UserUser", 
result_children=children)
+        self.expect_var_path("useruser", type="UserUser", children=children)
diff --git a/lldb/test/API/lang/cpp/virtual-bases/main.cpp 
b/lldb/test/API/lang/cpp/virtual-bases/main.cpp
new file mode 100644
index 0000000000000..8addd388dfcb2
--- /dev/null
+++ b/lldb/test/API/lang/cpp/virtual-bases/main.cpp
@@ -0,0 +1,30 @@
+struct VBase1 {
+  short member = 1;
+};
+struct VBase2 {
+  short member = 2;
+};
+
+struct Padding3 {
+  short member = 3;
+};
+struct Padding4 {
+  short member = 4;
+};
+struct Padding5 {
+  short member = 5;
+};
+
+struct User : public Padding3, public virtual VBase1, public virtual VBase2 {
+  short member = 6;
+};
+
+struct UserUser : public Padding4, public User, public Padding5 {
+  short member = 7;
+};
+
+int main() {
+  UserUser useruser;
+
+  return 0; // break here
+}

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to