Author: Nerixyz
Date: 2026-08-31T18:19:07+02:00
New Revision: 51e608f5ed8c799a7b61dd55496db984222b44d4

URL: 
https://github.com/llvm/llvm-project/commit/51e608f5ed8c799a7b61dd55496db984222b44d4
DIFF: 
https://github.com/llvm/llvm-project/commit/51e608f5ed8c799a7b61dd55496db984222b44d4.diff

LOG: [lldb][MSABI] Take offset of vbptr into account (#190679)

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)
```

Added: 
    

Modified: 
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
    lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
    lldb/test/API/lang/cpp/diamond/main.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index f11e78d4b008c..b0cebd12598dd 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


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

Reply via email to