2 Make sure the getting a variable path works and doesn't crash.
7 import lldbsuite
.test
.lldbutil
as lldbutil
8 from lldbsuite
.test
.decorators
import *
9 from lldbsuite
.test
.lldbtest
import *
11 class TestVTableValue(TestBase
):
12 # If your test case doesn't stress debug info, then
13 # set this to true. That way it won't be run once for
14 # each debug info format.
15 NO_DEBUG_INFO_TESTCASE
= True
17 @skipUnlessPlatform(["linux", "macosx"])
18 def test_vtable(self
):
20 lldbutil
.run_to_source_breakpoint(
21 self
, "At the end", lldb
.SBFileSpec("main.cpp")
24 # Test a shape instance to make sure we get the vtable correctly.
25 shape
= self
.frame().FindVariable("shape")
26 vtable
= shape
.GetVTable()
27 self
.assertEquals(vtable
.GetName(), "vtable for Shape")
28 self
.assertEquals(vtable
.GetTypeName(), "vtable for Shape")
29 # Make sure we have the right number of virtual functions in our vtable
30 # for the shape class.
31 self
.assertEquals(vtable
.GetNumChildren(), 4)
33 # Verify vtable address
34 vtable_addr
= vtable
.GetValueAsUnsigned(0)
35 expected_addr
= self
.expected_vtable_addr(shape
)
36 self
.assertEquals(vtable_addr
, expected_addr
)
38 for (idx
, vtable_entry
) in enumerate(vtable
.children
):
39 self
.verify_vtable_entry(vtable_entry
, vtable_addr
, idx
)
41 # Test a shape reference to make sure we get the vtable correctly.
42 shape
= self
.frame().FindVariable("shape_ref")
43 vtable
= shape
.GetVTable()
44 self
.assertEquals(vtable
.GetName(), "vtable for Shape")
45 self
.assertEquals(vtable
.GetTypeName(), "vtable for Shape")
46 # Make sure we have the right number of virtual functions in our vtable
47 # for the shape class.
48 self
.assertEquals(vtable
.GetNumChildren(), 4)
50 # Verify vtable address
51 vtable_addr
= vtable
.GetValueAsUnsigned(0)
52 expected_addr
= self
.expected_vtable_addr(shape
)
53 self
.assertEquals(vtable_addr
, expected_addr
)
55 for (idx
, vtable_entry
) in enumerate(vtable
.children
):
56 self
.verify_vtable_entry(vtable_entry
, vtable_addr
, idx
)
59 # Test we get the right vtable for the Rectangle instance.
60 rect
= self
.frame().FindVariable("rect")
61 vtable
= rect
.GetVTable()
62 self
.assertEquals(vtable
.GetName(), "vtable for Rectangle")
63 self
.assertEquals(vtable
.GetTypeName(), "vtable for Rectangle")
65 # Make sure we have the right number of virtual functions in our vtable
66 # with the extra virtual function added by the Rectangle class
67 self
.assertEquals(vtable
.GetNumChildren(), 5)
69 # Verify vtable address
70 vtable_addr
= vtable
.GetValueAsUnsigned()
71 expected_addr
= self
.expected_vtable_addr(rect
)
72 self
.assertEquals(vtable_addr
, expected_addr
)
74 for (idx
, vtable_entry
) in enumerate(vtable
.children
):
75 self
.verify_vtable_entry(vtable_entry
, vtable_addr
, idx
)
77 @skipUnlessPlatform(["linux", "macosx"])
78 def test_base_class_ptr(self
):
80 (target
, process
, thread
, bkpt
) = lldbutil
.run_to_source_breakpoint(
81 self
, "Shape is Rectangle", lldb
.SBFileSpec("main.cpp")
84 shape
= self
.frame().FindVariable("shape")
85 rect
= self
.frame().FindVariable("rect")
87 shape_ptr
= self
.frame().FindVariable("shape_ptr")
88 shape_ptr_vtable
= shape_ptr
.GetVTable()
89 self
.assertEquals(shape_ptr_vtable
.GetName(), "vtable for Rectangle")
90 self
.assertEquals(shape_ptr_vtable
.GetNumChildren(), 5)
91 self
.assertEquals(shape_ptr
.GetValueAsUnsigned(0),
92 rect
.GetLoadAddress())
93 lldbutil
.continue_to_source_breakpoint(
94 self
, process
, "Shape is Shape", lldb
.SBFileSpec("main.cpp")
96 self
.assertEquals(shape_ptr
.GetValueAsUnsigned(0),
97 shape
.GetLoadAddress())
98 self
.assertEquals(shape_ptr_vtable
.GetNumChildren(), 4)
99 self
.assertEquals(shape_ptr_vtable
.GetName(), "vtable for Shape")
101 @skipUnlessPlatform(["linux", "macosx"])
102 def test_no_vtable(self
):
104 lldbutil
.run_to_source_breakpoint(
105 self
, "At the end", lldb
.SBFileSpec("main.cpp")
108 var
= self
.frame().FindVariable("not_virtual")
109 self
.assertEqual(var
.GetVTable().GetError().GetCString(),
110 'type "NotVirtual" doesn\'t have a vtable')
112 var
= self
.frame().FindVariable("argc")
113 self
.assertEqual(var
.GetVTable().GetError().GetCString(),
114 'no language runtime support for the language "c"')
116 @skipUnlessPlatform(["linux", "macosx"])
117 def test_overwrite_vtable(self
):
119 (target
, process
, thread
, bkpt
) = lldbutil
.run_to_source_breakpoint(
120 self
, "At the end", lldb
.SBFileSpec("main.cpp")
123 # Test a shape instance to make sure we get the vtable correctly.
124 shape
= self
.frame().FindVariable("shape")
125 vtable
= shape
.GetVTable()
126 self
.assertEquals(vtable
.GetName(), "vtable for Shape")
127 self
.assertEquals(vtable
.GetTypeName(), "vtable for Shape")
128 # Make sure we have the right number of virtual functions in our vtable
129 # for the shape class.
130 self
.assertEquals(vtable
.GetNumChildren(), 4)
132 # Overwrite the first entry in the vtable and make sure we can still
133 # see the bogus value which should have no summary
134 vtable_addr
= vtable
.GetValueAsUnsigned()
135 data
= str("\x01\x01\x01\x01\x01\x01\x01\x01")
136 error
= lldb
.SBError()
137 process
.WriteMemory(vtable_addr
, data
, error
)
139 scribbled_child
= vtable
.GetChildAtIndex(0)
140 self
.assertEquals(scribbled_child
.GetValueAsUnsigned(0),
142 self
.assertEquals(scribbled_child
.GetSummary(), None)
144 def expected_vtable_addr(self
, var
: lldb
.SBValue
) -> int:
145 load_addr
= var
.GetLoadAddress()
146 read_from_memory_error
= lldb
.SBError()
147 vtable_addr
= self
.process().ReadPointerFromMemory(
148 load_addr
, read_from_memory_error
150 self
.assertTrue(read_from_memory_error
.Success())
153 def expected_vtable_entry_func_ptr(self
, vtable_addr
: int, idx
: int):
154 vtable_entry_addr
= vtable_addr
+ idx
* self
.process().GetAddressByteSize()
155 read_func_ptr_error
= lldb
.SBError()
156 func_ptr
= self
.process().ReadPointerFromMemory(vtable_entry_addr
,
158 self
.assertTrue(read_func_ptr_error
.Success())
161 def verify_vtable_entry(self
, vtable_entry
: lldb
.SBValue
, vtable_addr
: int,
163 """Verify the vtable entry looks something like:
165 (double ()) [0] = 0x0000000100003a10 a.out`Rectangle::Area() at main.cpp:14
169 vtable_entry_func_ptr
= vtable_entry
.GetValueAsUnsigned(0)
171 vtable_entry_func_ptr
,
172 self
.expected_vtable_entry_func_ptr(vtable_addr
, idx
),
175 sb_addr
= self
.target().ResolveLoadAddress(vtable_entry_func_ptr
)
176 sym_ctx
= sb_addr
.GetSymbolContext(lldb
.eSymbolContextEverything
)
178 # Make sure the type is the same as the function type
179 func_type
= sym_ctx
.GetFunction().GetType()
180 if func_type
.IsValid():
181 self
.assertEquals(vtable_entry
.GetType(),
182 func_type
.GetPointerType())
184 # The summary should be the address description of the function pointer
185 summary
= vtable_entry
.GetSummary()
186 self
.assertEquals(str(sb_addr
), summary
)