brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · d8260a5 Raw
278 lines · python
1"""2Make sure the frame variable -g, -a, and -l flags work.3"""4 5import lldb6import lldbsuite.test.lldbutil as lldbutil7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9import os10import shutil11import time12 13 14class TestFrameVar(TestBase):15    # If your test case doesn't stress debug info, then16    # set this to true.  That way it won't be run once for17    # each debug info format.18    NO_DEBUG_INFO_TESTCASE = True19 20    def test_frame_var(self):21        self.build()22        self.do_test()23 24    def do_test(self):25        target = self.createTestTarget()26 27        # Now create a breakpoint in main.c at the source matching28        # "Set a breakpoint here"29        breakpoint = target.BreakpointCreateBySourceRegex(30            "Set a breakpoint here", lldb.SBFileSpec("main.c")31        )32        self.assertTrue(33            breakpoint and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT34        )35 36        error = lldb.SBError()37        # This is the launch info.  If you want to launch with arguments or38        # environment variables, add them using SetArguments or39        # SetEnvironmentEntries40 41        launch_info = target.GetLaunchInfo()42        process = target.Launch(launch_info, error)43        self.assertTrue(process, PROCESS_IS_VALID)44 45        # Did we hit our breakpoint?46        from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint47 48        threads = get_threads_stopped_at_breakpoint(process, breakpoint)49        self.assertEqual(50            len(threads), 1, "There should be a thread stopped at our breakpoint"51        )52 53        # The hit count for the breakpoint should be 1.54        self.assertEqual(breakpoint.GetHitCount(), 1)55 56        frame = threads[0].GetFrameAtIndex(0)57        command_result = lldb.SBCommandReturnObject()58        interp = self.dbg.GetCommandInterpreter()59 60        # Ensure --regex can find globals if it is the very first frame var command.61        self.expect("frame var --regex g_", substrs=["g_var"])62 63        # Ensure the requested scope is respected:64        self.expect(65            "frame var --regex argc --no-args",66            error=True,67            substrs=["no variables matched the regular expression 'argc'"],68        )69 70        # Just get args:71        result = interp.HandleCommand("frame var -l", command_result)72        self.assertEqual(73            result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed"74        )75        output = command_result.GetOutput()76        self.assertIn("argc", output, "Args didn't find argc")77        self.assertIn("argv", output, "Args didn't find argv")78        self.assertNotIn("test_var", output, "Args found a local")79        self.assertNotIn("g_var", output, "Args found a global")80 81        value_list = command_result.GetValues(lldb.eNoDynamicValues)82        self.assertGreaterEqual(value_list.GetSize(), 2)83        value_names = []84        for value in value_list:85            value_names.append(value.GetName())86        self.assertIn("argc", value_names)87        self.assertIn("argv", value_names)88 89        # Just get locals:90        result = interp.HandleCommand("frame var -a", command_result)91        self.assertEqual(92            result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed"93        )94        output = command_result.GetOutput()95        self.assertNotIn("argc", output, "Locals found argc")96        self.assertNotIn("argv", output, "Locals found argv")97        self.assertIn("test_var", output, "Locals didn't find test_var")98        self.assertNotIn("g_var", output, "Locals found a global")99 100        # Get the file statics:101        result = interp.HandleCommand("frame var -l -a -g", command_result)102        self.assertEqual(103            result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed"104        )105        output = command_result.GetOutput()106        self.assertNotIn("argc", output, "Globals found argc")107        self.assertNotIn("argv", output, "Globals found argv")108        self.assertNotIn("test_var", output, "Globals found test_var")109        self.assertIn("g_var", output, "Globals didn't find g_var")110 111    def check_frame_variable_errors(self, thread, error_strings):112        command_result = lldb.SBCommandReturnObject()113        interp = self.dbg.GetCommandInterpreter()114        result = interp.HandleCommand("frame variable", command_result)115        self.assertEqual(116            result, lldb.eReturnStatusFailed, "frame var succeeded unexpectedly"117        )118        command_error = command_result.GetError()119 120        frame = thread.GetFrameAtIndex(0)121        var_list = frame.GetVariables(True, True, False, True)122        self.assertEqual(var_list.GetSize(), 0)123        api_error = var_list.GetError()124        api_error_str = api_error.GetCString()125 126        for s in error_strings:127            self.assertIn(s, command_error)128        for s in error_strings:129            self.assertIn(s, api_error_str)130 131        # Check the structured error data.132        data = api_error.GetErrorData()133        version = data.GetValueForKey("version")134        self.assertEqual(version.GetIntegerValue(), 1)135        err_ty = data.GetValueForKey("type")136        self.assertEqual(err_ty.GetIntegerValue(), lldb.eErrorTypeGeneric)137        message = str(data.GetValueForKey("errors").GetItemAtIndex(0))138        for s in error_strings:139            self.assertIn(s, message)140 141    @skipIfRemote142    @skipUnlessDarwin143    def test_darwin_dwarf_missing_obj(self):144        """145        Test that if we build a binary with DWARF in .o files and we remove146        the .o file for main.cpp, that we get an appropriate error when we147        do 'frame variable' that explains why we aren't seeing variables.148        """149        self.build(debug_info="dwarf")150        exe = self.getBuildArtifact("a.out")151        main_obj = self.getBuildArtifact("main.o")152        # Delete the main.o file that contains the debug info so we force an153        # error when we run to main and try to get variables154        os.unlink(main_obj)155 156        # We have to set a named breakpoint because we don't have any debug info157        # because we deleted the main.o file.158        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, "main")159        error_strings = [160            'debug map object file "',161            'main.o" containing debug info does not exist, debug info will not be loaded',162        ]163        self.check_frame_variable_errors(thread, error_strings)164 165    @skipIfRemote166    @skipUnlessDarwin167    def test_darwin_dwarf_obj_mod_time_mismatch(self):168        """169        Test that if we build a binary with DWARF in .o files and we update170        the mod time of the .o file for main.cpp, that we get an appropriate171        error when we do 'frame variable' that explains why we aren't seeing172        variables.173        """174        self.build(debug_info="dwarf")175        exe = self.getBuildArtifact("a.out")176        main_obj = self.getBuildArtifact("main.o")177 178        # Set the modification time for main.o file to the current time after179        # sleeping for 2 seconds. This ensures the modification time will have180        # changed and will not match the modification time in the debug map and181        # force an error when we run to main and try to get variables182        time.sleep(2)183        os.utime(main_obj, None)184 185        # We have to set a named breakpoint because we don't have any debug info186        # because we deleted the main.o file since the mod times don't match187        # and debug info won't be loaded188        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, "main")189 190        error_strings = [191            'debug map object file "',192            'main.o" changed (actual: 0x',193            ", debug map: 0x",194            ") since this executable was linked, debug info will not be loaded",195        ]196        self.check_frame_variable_errors(thread, error_strings)197 198    @skipIfRemote199    @skipIfWindows  # Windows can't set breakpoints by name 'main' in this case.200    def test_gline_tables_only(self):201        """202        Test that if we build a binary with "-gline-tables-only" that we can203        set a file and line breakpoint successfully, and get an error204        letting us know that this build option was enabled when trying to205        read variables.206        """207        self.build(dictionary={"CFLAGS_EXTRAS": "-gline-tables-only"})208        exe = self.getBuildArtifact("a.out")209 210        # We have to set a named breakpoint because we don't have any debug info211        # because we deleted the main.o file since the mod times don't match212        # and debug info won't be loaded213        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, "main")214        error_strings = [215            "no variable information is available in debug info for this compile unit"216        ]217        self.check_frame_variable_errors(thread, error_strings)218 219    @skipUnlessPlatform(["linux", "freebsd"])220    @add_test_categories(["dwo"])221    def test_fission_missing_dwo(self):222        """223        Test that if we build a binary with "-gsplit-dwarf" that we can224        set a file and line breakpoint successfully, and get an error225        letting us know we were unable to load the .dwo file.226        """227        self.build(dictionary={"CFLAGS_EXTRAS": "-gsplit-dwarf"})228        exe = self.getBuildArtifact("a.out")229        main_dwo = self.getBuildArtifact("main.dwo")230 231        self.assertTrue(232            os.path.exists(main_dwo), 'Make sure "%s" file exists' % (main_dwo)233        )234        # Delete the main.dwo file that contains the debug info so we force an235        # error when we run to main and try to get variables.236        os.unlink(main_dwo)237 238        # We have to set a named breakpoint because we don't have any debug info239        # because we deleted the main.o file since the mod times don't match240        # and debug info won't be loaded241        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, "main")242        error_strings = [243            'unable to locate .dwo debug file "',244            'main.dwo" for skeleton DIE 0x',245        ]246        self.check_frame_variable_errors(thread, error_strings)247 248    @skipUnlessPlatform(["linux", "freebsd"])249    @add_test_categories(["dwo"])250    def test_fission_invalid_dwo_objectfile(self):251        """252        Test that if we build a binary with "-gsplit-dwarf" that we can253        set a file and line breakpoint successfully, and get an error254        letting us know we were unable to load the .dwo file because it255        existed, but it wasn't a valid object file.256        """257        self.build(dictionary={"CFLAGS_EXTRAS": "-gsplit-dwarf"})258        exe = self.getBuildArtifact("a.out")259        main_dwo = self.getBuildArtifact("main.dwo")260 261        self.assertTrue(262            os.path.exists(main_dwo), 'Make sure "%s" file exists' % (main_dwo)263        )264        # Overwrite the main.dwo with the main.c source file so that the .dwo265        # file exists, but it isn't a valid object file as there is an error266        # for this case.267        shutil.copyfile(self.getSourcePath("main.c"), main_dwo)268 269        # We have to set a named breakpoint because we don't have any debug info270        # because we deleted the main.o file since the mod times don't match271        # and debug info won't be loaded272        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, "main")273        error_strings = [274            'unable to load object file for .dwo debug file "'275            'main.dwo" for unit DIE 0x',276        ]277        self.check_frame_variable_errors(thread, error_strings)278