llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Nerixyz (Nerixyz) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/214960.diff 4 Files Affected: - (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+4) - (added) lldb/test/API/lang/cpp/virtual-bases/Makefile (+3) - (added) lldb/test/API/lang/cpp/virtual-bases/TestCppVirtualBases.py (+49) - (added) lldb/test/API/lang/cpp/virtual-bases/main.cpp (+30) ``````````diff 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 +} `````````` </details> https://github.com/llvm/llvm-project/pull/214960 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
