Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / functionalities / vtable / TestVTableValue.py
blob5b243e0646f4c2824702f3d9e123a13788194aaa
1 """
2 Make sure the getting a variable path works and doesn't crash.
3 """
6 import lldb
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):
19 self.build()
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):
79 self.build()
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):
103 self.build()
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):
118 self.build()
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),
141 0x0101010101010101)
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())
151 return vtable_addr
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,
157 read_func_ptr_error)
158 self.assertTrue(read_func_ptr_error.Success())
159 return func_ptr
161 def verify_vtable_entry(self, vtable_entry: lldb.SBValue, vtable_addr: int,
162 idx: int):
163 """Verify the vtable entry looks something like:
165 (double ()) [0] = 0x0000000100003a10 a.out`Rectangle::Area() at main.cpp:14
168 # Check function ptr
169 vtable_entry_func_ptr = vtable_entry.GetValueAsUnsigned(0)
170 self.assertEquals(
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)