brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · f0076ea Raw
202 lines · python
1"""2Make sure the getting a variable path works and doesn't crash.3"""4 5import lldb6import lldbsuite.test.lldbutil as lldbutil7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9 10 11class TestVTableValue(TestBase):12    # If your test case doesn't stress debug info, then13    # set this to true.  That way it won't be run once for14    # each debug info format.15    NO_DEBUG_INFO_TESTCASE = True16 17    @skipIf(compiler="clang", compiler_version=["<", "9.0"])18    @skipUnlessPlatform(["linux", "macosx"])19    def test_vtable(self):20        self.build()21        lldbutil.run_to_source_breakpoint(22            self, "At the end", lldb.SBFileSpec("main.cpp")23        )24 25        # Test a shape instance to make sure we get the vtable correctly.26        shape = self.frame().FindVariable("shape")27        vtable = shape.GetVTable()28        self.assertEqual(vtable.GetName(), "vtable for Shape")29        self.assertEqual(vtable.GetTypeName(), "vtable for Shape")30        # Make sure we have the right number of virtual functions in our vtable31        # for the shape class.32        self.assertEqual(vtable.GetNumChildren(), 4)33 34        # Verify vtable address35        vtable_addr = vtable.GetValueAsUnsigned(0)36        expected_addr = self.expected_vtable_addr(shape)37        self.assertEqual(vtable_addr, expected_addr)38 39        for idx, vtable_entry in enumerate(vtable.children):40            self.verify_vtable_entry(vtable_entry, vtable_addr, idx)41 42        # Test a shape reference to make sure we get the vtable correctly.43        shape = self.frame().FindVariable("shape_ref")44        vtable = shape.GetVTable()45        self.assertEqual(vtable.GetName(), "vtable for Shape")46        self.assertEqual(vtable.GetTypeName(), "vtable for Shape")47        # Make sure we have the right number of virtual functions in our vtable48        # for the shape class.49        self.assertEqual(vtable.GetNumChildren(), 4)50 51        # Verify vtable address52        vtable_addr = vtable.GetValueAsUnsigned(0)53        expected_addr = self.expected_vtable_addr(shape)54        self.assertEqual(vtable_addr, expected_addr)55 56        for idx, vtable_entry in enumerate(vtable.children):57            self.verify_vtable_entry(vtable_entry, vtable_addr, idx)58 59        # Test we get the right vtable for the Rectangle instance.60        rect = self.frame().FindVariable("rect")61        vtable = rect.GetVTable()62        self.assertEqual(vtable.GetName(), "vtable for Rectangle")63        self.assertEqual(vtable.GetTypeName(), "vtable for Rectangle")64 65        # Make sure we have the right number of virtual functions in our vtable66        # with the extra virtual function added by the Rectangle class67        self.assertEqual(vtable.GetNumChildren(), 5)68 69        # Verify vtable address70        vtable_addr = vtable.GetValueAsUnsigned()71        expected_addr = self.expected_vtable_addr(rect)72        self.assertEqual(vtable_addr, expected_addr)73 74        for idx, vtable_entry in enumerate(vtable.children):75            self.verify_vtable_entry(vtable_entry, vtable_addr, idx)76 77    @skipIf(compiler="clang", compiler_version=["<", "9.0"])78    @skipUnlessPlatform(["linux", "macosx"])79    def test_base_class_ptr(self):80        self.build()81        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(82            self, "Shape is Rectangle", lldb.SBFileSpec("main.cpp")83        )84 85        shape = self.frame().FindVariable("shape")86        rect = self.frame().FindVariable("rect")87 88        shape_ptr = self.frame().FindVariable("shape_ptr")89        shape_ptr_vtable = shape_ptr.GetVTable()90        self.assertEqual(shape_ptr_vtable.GetName(), "vtable for Rectangle")91        self.assertEqual(shape_ptr_vtable.GetNumChildren(), 5)92        self.assertEqual(shape_ptr.GetValueAsUnsigned(0), rect.GetLoadAddress())93        lldbutil.continue_to_source_breakpoint(94            self, process, "Shape is Shape", lldb.SBFileSpec("main.cpp")95        )96        self.assertEqual(shape_ptr.GetValueAsUnsigned(0), shape.GetLoadAddress())97        self.assertEqual(shape_ptr_vtable.GetNumChildren(), 4)98        self.assertEqual(shape_ptr_vtable.GetName(), "vtable for Shape")99 100    @skipUnlessPlatform(["linux", "macosx"])101    def test_no_vtable(self):102        self.build()103        lldbutil.run_to_source_breakpoint(104            self, "At the end", lldb.SBFileSpec("main.cpp")105        )106 107        var = self.frame().FindVariable("not_virtual")108        self.assertEqual(109            var.GetVTable().GetError().GetCString(),110            'type "NotVirtual" doesn\'t have a vtable',111        )112 113        var = self.frame().FindVariable("argc")114        self.assertEqual(115            var.GetVTable().GetError().GetCString(),116            'no language runtime support for the language "c"',117        )118 119    @skipUnlessPlatform(["linux", "macosx"])120    def test_overwrite_vtable(self):121        self.build()122        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(123            self, "At the end", lldb.SBFileSpec("main.cpp")124        )125 126        # Test a shape instance to make sure we get the vtable correctly.127        shape = self.frame().FindVariable("shape")128        vtable = shape.GetVTable()129        self.assertEqual(vtable.GetName(), "vtable for Shape")130        self.assertEqual(vtable.GetTypeName(), "vtable for Shape")131        # Make sure we have the right number of virtual functions in our vtable132        # for the shape class.133        self.assertEqual(vtable.GetNumChildren(), 4)134 135        # Overwrite the first entry in the vtable and make sure we can still136        # see the bogus value which should have no summary137        vtable_addr = vtable.GetValueAsUnsigned()138 139        is_64bit = self.process().GetAddressByteSize() == 8140        data = str(141            "\x01\x01\x01\x01\x01\x01\x01\x01" if is_64bit else "\x01\x01\x01\x01"142        )143        error = lldb.SBError()144        bytes_written = process.WriteMemory(vtable_addr, data, error)145 146        self.assertSuccess(error)147        self.assertGreater(148            bytes_written, 0, "Failed to overwrite first entry in vtable"149        )150 151        scribbled_child = vtable.GetChildAtIndex(0)152        self.assertEqual(153            scribbled_child.GetValueAsUnsigned(0),154            0x0101010101010101 if is_64bit else 0x01010101,155        )156        self.assertEqual(scribbled_child.GetSummary(), None)157 158    def expected_vtable_addr(self, var: lldb.SBValue) -> int:159        load_addr = var.GetLoadAddress()160        read_from_memory_error = lldb.SBError()161        vtable_addr = self.process().ReadPointerFromMemory(162            load_addr, read_from_memory_error163        )164        self.assertTrue(read_from_memory_error.Success())165        return vtable_addr166 167    def expected_vtable_entry_func_ptr(self, vtable_addr: int, idx: int):168        vtable_entry_addr = vtable_addr + idx * self.process().GetAddressByteSize()169        read_func_ptr_error = lldb.SBError()170        func_ptr = self.process().ReadPointerFromMemory(171            vtable_entry_addr, read_func_ptr_error172        )173        self.assertTrue(read_func_ptr_error.Success())174        return func_ptr175 176    def verify_vtable_entry(177        self, vtable_entry: lldb.SBValue, vtable_addr: int, idx: int178    ):179        """Verify the vtable entry looks something like:180 181        (double ()) [0] = 0x0000000100003a10 a.out`Rectangle::Area() at main.cpp:14182 183        """184        # Check function ptr185        vtable_entry_func_ptr = vtable_entry.GetValueAsUnsigned(0)186        self.assertEqual(187            vtable_entry_func_ptr,188            self.expected_vtable_entry_func_ptr(vtable_addr, idx),189        )190 191        sb_addr = self.target().ResolveLoadAddress(vtable_entry_func_ptr)192        sym_ctx = sb_addr.GetSymbolContext(lldb.eSymbolContextEverything)193 194        # Make sure the type is the same as the function type195        func_type = sym_ctx.GetFunction().GetType()196        if func_type.IsValid():197            self.assertEqual(vtable_entry.GetType(), func_type.GetPointerType())198 199        # The summary should be the address description of the function pointer200        summary = vtable_entry.GetSummary()201        self.assertEqual(str(sb_addr), summary)202