brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.6 KiB · 411ce9c Raw
541 lines · python
1"""2Test breakpoint serialization.3"""4 5import os6import json7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10from lldbsuite.test import lldbutil11 12 13class BreakpointSerialization(TestBase):14    NO_DEBUG_INFO_TESTCASE = True15 16    @add_test_categories(["pyapi"])17    def test_resolvers(self):18        """Use Python APIs to test that we serialize resolvers."""19        self.build()20        self.setup_targets_and_cleanup()21        self.do_check_resolvers()22 23    def test_filters(self):24        """Use Python APIs to test that we serialize search filters correctly."""25        self.build()26        self.setup_targets_and_cleanup()27        self.do_check_filters()28 29    def test_options(self):30        """Use Python APIs to test that we serialize breakpoint options correctly."""31        self.build()32        self.setup_targets_and_cleanup()33        self.do_check_options()34 35    def test_appending(self):36        """Use Python APIs to test that we serialize breakpoint options correctly."""37        self.build()38        self.setup_targets_and_cleanup()39        self.do_check_appending()40 41    def test_name_filters(self):42        """Use python APIs to test that reading in by name works correctly."""43        self.build()44        self.setup_targets_and_cleanup()45        self.do_check_names()46 47    def test_scripted_extra_args(self):48        self.build()49        self.setup_targets_and_cleanup()50        self.do_check_extra_args()51 52    def test_resolver_serialization(self):53        """Test that breakpoint resolvers contain the expected information"""54        self.build()55        self.setup_targets_and_cleanup()56 57        exe_path = self.getBuildArtifact("a.out")58        exe_module = self.orig_target.module["a.out"]59        self.assertTrue(60            exe_module.IsValid(), "Failed to find the executable module in target"61        )62        sym_ctx_list = exe_module.FindFunctions("main")63        self.assertEqual(sym_ctx_list.GetSize(), 1, "Unable to find function 'main'")64        sym_ctx = sym_ctx_list.GetContextAtIndex(0)65        self.assertTrue(66            sym_ctx.IsValid(), "SBSymbolContext representing function 'main' is invalid"67        )68        main_func = sym_ctx.GetFunction()69        self.assertTrue(70            main_func.IsValid(), "SBFunction representing 'main' is invalid"71        )72        main_addr = main_func.GetStartAddress()73 74        bkpt = self.orig_target.BreakpointCreateBySBAddress(main_addr)75        self.assertTrue(76            bkpt.IsValid(), "Could not place breakpoint on 'main' by address"77        )78        stream = lldb.SBStream()79        sd = bkpt.SerializeToStructuredData()80        sd.GetAsJSON(stream)81        serialized_data = json.loads(stream.GetData())82 83        self.assertIn(84            exe_path,85            serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["ModuleName"],86        )87 88    def test_structured_data_serialization(self):89        target = self.dbg.GetDummyTarget()90        self.assertTrue(target.IsValid(), VALID_TARGET)91 92        interpreter = self.dbg.GetCommandInterpreter()93        result = lldb.SBCommandReturnObject()94        interpreter.HandleCommand("br set -f foo -l 42", result)95        result = lldb.SBCommandReturnObject()96        interpreter.HandleCommand("br set -c 'argc == 1' -n main", result)97 98        bkp1 = target.GetBreakpointAtIndex(0)99        self.assertTrue(bkp1.IsValid(), VALID_BREAKPOINT)100        stream = lldb.SBStream()101        sd = bkp1.SerializeToStructuredData()102        sd.GetAsJSON(stream)103        serialized_data = json.loads(stream.GetData())104        self.assertEqual(105            serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["FileName"], "foo"106        )107        self.assertEqual(108            serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["LineNumber"], 42109        )110 111        bkp2 = target.GetBreakpointAtIndex(1)112        self.assertTrue(bkp2.IsValid(), VALID_BREAKPOINT)113        stream = lldb.SBStream()114        sd = bkp2.SerializeToStructuredData()115        sd.GetAsJSON(stream)116        serialized_data = json.loads(stream.GetData())117        self.assertIn(118            "main",119            serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["SymbolNames"],120        )121        self.assertEqual(122            serialized_data["Breakpoint"]["BKPTOptions"]["ConditionText"], "argc == 1"123        )124 125        invalid_bkp = lldb.SBBreakpoint()126        self.assertFalse(invalid_bkp.IsValid(), "Breakpoint should not be valid.")127        stream = lldb.SBStream()128        sd = invalid_bkp.SerializeToStructuredData()129        sd.GetAsJSON(stream)130        self.assertFalse(131            stream.GetData(), "Invalid breakpoint should have an empty structured data"132        )133 134    def setup_targets_and_cleanup(self):135        def cleanup():136            self.RemoveTempFile(self.bkpts_file_path)137 138            if self.orig_target.IsValid():139                self.dbg.DeleteTarget(self.orig_target)140                self.dbg.DeleteTarget(self.copy_target)141 142        self.addTearDownHook(cleanup)143        self.RemoveTempFile(self.bkpts_file_path)144 145        exe = self.getBuildArtifact("a.out")146 147        # Create the targets we are making breakpoints in and copying them to:148        self.orig_target = self.dbg.CreateTarget(exe)149        self.assertTrue(self.orig_target, VALID_TARGET)150 151        self.copy_target = self.dbg.CreateTarget(exe)152        self.assertTrue(self.copy_target, VALID_TARGET)153 154    def setUp(self):155        # Call super's setUp().156        TestBase.setUp(self)157 158        self.bkpts_file_path = self.getBuildArtifact("breakpoints.json")159        self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path)160 161    def check_equivalence(self, source_bps, do_write=True):162        error = lldb.SBError()163 164        if do_write:165            error = self.orig_target.BreakpointsWriteToFile(166                self.bkpts_file_spec, source_bps167            )168            self.assertSuccess(error, "Failed writing breakpoints to file")169 170        copy_bps = lldb.SBBreakpointList(self.copy_target)171        error = self.copy_target.BreakpointsCreateFromFile(172            self.bkpts_file_spec, copy_bps173        )174        self.assertSuccess(error, "Failed reading breakpoints from file")175 176        num_source_bps = source_bps.GetSize()177        num_copy_bps = copy_bps.GetSize()178        self.assertEqual(179            num_source_bps,180            num_copy_bps,181            "Didn't get same number of input and output breakpoints - orig: %d copy: %d"182            % (num_source_bps, num_copy_bps),183        )184 185        for i in range(0, num_source_bps):186            source_bp = source_bps.GetBreakpointAtIndex(i)187            source_desc = lldb.SBStream()188            source_bp.GetDescription(source_desc, False)189            source_text = source_desc.GetData()190 191            # I am assuming here that the breakpoints will get written out in breakpoint ID order, and192            # read back in ditto.  That is true right now, and I can't see any reason to do it differently193            # but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to194            # see which one is which.195            copy_id = source_bp.GetID()196            copy_bp = copy_bps.FindBreakpointByID(copy_id)197            self.assertTrue(198                copy_bp.IsValid(), "Could not find copy breakpoint %d." % (copy_id)199            )200 201            copy_desc = lldb.SBStream()202            copy_bp.GetDescription(copy_desc, False)203            copy_text = copy_desc.GetData()204 205            # These two should be identical.206            self.trace("Source text for %d is %s." % (i, source_text))207            self.assertEqual(208                source_text,209                copy_text,210                "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"211                % (source_text, copy_text),212            )213 214    def do_check_resolvers(self):215        """Use Python APIs to check serialization of breakpoint resolvers"""216 217        empty_module_list = lldb.SBFileSpecList()218        empty_cu_list = lldb.SBFileSpecList()219        blubby_file_spec = lldb.SBFileSpec(220            os.path.join(self.getSourceDir(), "blubby.c")221        )222 223        # It isn't actually important for these purposes that these breakpoint224        # actually have locations.225        source_bps = lldb.SBBreakpointList(self.orig_target)226        source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666))227        # Make sure we do one breakpoint right:228        self.check_equivalence(source_bps)229        source_bps.Clear()230 231        source_bps.Append(232            self.orig_target.BreakpointCreateByName(233                "blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list234            )235        )236        source_bps.Append(237            self.orig_target.BreakpointCreateByName(238                "blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list239            )240        )241        source_bps.Append(242            self.orig_target.BreakpointCreateBySourceRegex(243                "dont really care", blubby_file_spec244            )245        )246 247        # And some number greater than one:248        self.check_equivalence(source_bps)249 250    def do_check_filters(self):251        """Use Python APIs to check serialization of breakpoint filters."""252        module_list = lldb.SBFileSpecList()253        module_list.Append(lldb.SBFileSpec("SomeBinary"))254        module_list.Append(lldb.SBFileSpec("SomeOtherBinary"))255 256        cu_list = lldb.SBFileSpecList()257        cu_list.Append(lldb.SBFileSpec("SomeCU.c"))258        cu_list.Append(lldb.SBFileSpec("AnotherCU.c"))259        cu_list.Append(lldb.SBFileSpec("ThirdCU.c"))260 261        blubby_file_spec = lldb.SBFileSpec(262            os.path.join(self.getSourceDir(), "blubby.c")263        )264 265        # It isn't actually important for these purposes that these breakpoint266        # actually have locations.267        source_bps = lldb.SBBreakpointList(self.orig_target)268        bkpt = self.orig_target.BreakpointCreateByLocation(269            blubby_file_spec, 666, 0, module_list270        )271        source_bps.Append(bkpt)272 273        # Make sure we do one right:274        self.check_equivalence(source_bps)275        source_bps.Clear()276 277        bkpt = self.orig_target.BreakpointCreateByName(278            "blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list279        )280        source_bps.Append(bkpt)281        bkpt = self.orig_target.BreakpointCreateByName(282            "blubby", lldb.eFunctionNameTypeFull, module_list, cu_list283        )284        source_bps.Append(bkpt)285        bkpt = self.orig_target.BreakpointCreateBySourceRegex(286            "dont really care", blubby_file_spec287        )288        source_bps.Append(bkpt)289 290        # And some number greater than one:291        self.check_equivalence(source_bps)292 293    def do_check_options(self):294        """Use Python APIs to check serialization of breakpoint options."""295 296        empty_module_list = lldb.SBFileSpecList()297        empty_cu_list = lldb.SBFileSpecList()298        blubby_file_spec = lldb.SBFileSpec(299            os.path.join(self.getSourceDir(), "blubby.c")300        )301 302        # It isn't actually important for these purposes that these breakpoint303        # actually have locations.304        source_bps = lldb.SBBreakpointList(self.orig_target)305 306        bkpt = self.orig_target.BreakpointCreateByLocation(307            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()308        )309        bkpt.SetEnabled(False)310        bkpt.SetOneShot(True)311        bkpt.SetThreadID(10)312        source_bps.Append(bkpt)313 314        # Make sure we get one right:315        self.check_equivalence(source_bps)316        source_bps.Clear()317 318        bkpt = self.orig_target.BreakpointCreateByName(319            "blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list320        )321        bkpt.SetIgnoreCount(10)322        bkpt.SetThreadName("grubby")323        source_bps.Append(bkpt)324 325        bkpt = self.orig_target.BreakpointCreateByName(326            "blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list327        )328        bkpt.SetCondition("gonna remove this")329        bkpt.SetCondition("")330        source_bps.Append(bkpt)331 332        bkpt = self.orig_target.BreakpointCreateByName(333            "blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list334        )335        bkpt.SetCondition("something != something_else")336        bkpt.SetQueueName("grubby")337        bkpt.AddName("FirstName")338        bkpt.AddName("SecondName")339        bkpt.SetScriptCallbackBody(340            '\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n'341        )342        source_bps.Append(bkpt)343 344        bkpt = self.orig_target.BreakpointCreateBySourceRegex(345            "dont really care", blubby_file_spec346        )347        cmd_list = lldb.SBStringList()348        cmd_list.AppendString("frame var")349        cmd_list.AppendString("thread backtrace")350 351        bkpt.SetCommandLineCommands(cmd_list)352        source_bps.Append(bkpt)353 354        self.check_equivalence(source_bps)355 356    def do_check_appending(self):357        """Use Python APIs to check appending to already serialized options."""358 359        empty_module_list = lldb.SBFileSpecList()360        empty_cu_list = lldb.SBFileSpecList()361        blubby_file_spec = lldb.SBFileSpec(362            os.path.join(self.getSourceDir(), "blubby.c")363        )364 365        # It isn't actually important for these purposes that these breakpoint366        # actually have locations.367 368        all_bps = lldb.SBBreakpointList(self.orig_target)369        source_bps = lldb.SBBreakpointList(self.orig_target)370 371        bkpt = self.orig_target.BreakpointCreateByLocation(372            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()373        )374        bkpt.SetEnabled(False)375        bkpt.SetOneShot(True)376        bkpt.SetThreadID(10)377        source_bps.Append(bkpt)378        all_bps.Append(bkpt)379 380        error = lldb.SBError()381        error = self.orig_target.BreakpointsWriteToFile(382            self.bkpts_file_spec, source_bps383        )384        self.assertSuccess(error, "Failed writing breakpoints to file")385 386        source_bps.Clear()387 388        bkpt = self.orig_target.BreakpointCreateByName(389            "blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list390        )391        bkpt.SetIgnoreCount(10)392        bkpt.SetThreadName("grubby")393        source_bps.Append(bkpt)394        all_bps.Append(bkpt)395 396        bkpt = self.orig_target.BreakpointCreateByName(397            "blubby", lldb.eFunctionNameTypeFull, empty_module_list, empty_cu_list398        )399        bkpt.SetCondition("something != something_else")400        bkpt.SetQueueName("grubby")401        bkpt.AddName("FirstName")402        bkpt.AddName("SecondName")403 404        source_bps.Append(bkpt)405        all_bps.Append(bkpt)406 407        error = self.orig_target.BreakpointsWriteToFile(408            self.bkpts_file_spec, source_bps, True409        )410        self.assertSuccess(error, "Failed appending breakpoints to file")411 412        self.check_equivalence(all_bps)413 414    def do_check_names(self):415        bkpt = self.orig_target.BreakpointCreateByLocation(416            lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()417        )418        good_bkpt_name = "GoodBreakpoint"419        write_bps = lldb.SBBreakpointList(self.orig_target)420        bkpt.AddName(good_bkpt_name)421        write_bps.Append(bkpt)422 423        error = lldb.SBError()424        error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)425        self.assertSuccess(error, "Failed writing breakpoints to file")426 427        copy_bps = lldb.SBBreakpointList(self.copy_target)428        names_list = lldb.SBStringList()429        names_list.AppendString("NoSuchName")430 431        error = self.copy_target.BreakpointsCreateFromFile(432            self.bkpts_file_spec, names_list, copy_bps433        )434        self.assertSuccess(error, "Failed reading breakpoints from file")435        self.assertEqual(436            copy_bps.GetSize(), 0, "Found breakpoints with a nonexistent name."437        )438 439        names_list.AppendString(good_bkpt_name)440        error = self.copy_target.BreakpointsCreateFromFile(441            self.bkpts_file_spec, names_list, copy_bps442        )443        self.assertSuccess(error, "Failed reading breakpoints from file")444        self.assertEqual(copy_bps.GetSize(), 1, "Found the matching breakpoint.")445 446    def do_check_extra_args(self):447        import side_effect448 449        interp = self.dbg.GetCommandInterpreter()450        error = lldb.SBError()451 452        script_name = os.path.join(self.getSourceDir(), "resolver.py")453 454        command = "command script import " + script_name455        result = lldb.SBCommandReturnObject()456        interp.HandleCommand(command, result)457        self.assertTrue(458            result.Succeeded(), "com scr imp failed: %s" % (result.GetError())459        )460 461        # First make sure a scripted breakpoint with no args works:462        bkpt = self.orig_target.BreakpointCreateFromScript(463            "resolver.Resolver",464            lldb.SBStructuredData(),465            lldb.SBFileSpecList(),466            lldb.SBFileSpecList(),467        )468        self.assertTrue(bkpt.IsValid(), "Bkpt is valid")469        write_bps = lldb.SBBreakpointList(self.orig_target)470 471        error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)472        self.assertSuccess(error, "Failed writing breakpoints")473 474        side_effect.g_extra_args = None475        copy_bps = lldb.SBBreakpointList(self.copy_target)476        error = self.copy_target.BreakpointsCreateFromFile(477            self.bkpts_file_spec, copy_bps478        )479        self.assertSuccess(error, "Failed reading breakpoints")480 481        self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")482        no_keys = lldb.SBStringList()483        side_effect.g_extra_args.GetKeys(no_keys)484        self.assertEqual(no_keys.GetSize(), 0, "Should have no keys")485 486        self.orig_target.DeleteAllBreakpoints()487        self.copy_target.DeleteAllBreakpoints()488 489        # Now try one with extra args:490 491        extra_args = lldb.SBStructuredData()492        stream = lldb.SBStream()493        stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}')494        extra_args.SetFromJSON(stream)495        self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.")496 497        bkpt = self.orig_target.BreakpointCreateFromScript(498            "resolver.Resolver",499            extra_args,500            lldb.SBFileSpecList(),501            lldb.SBFileSpecList(),502        )503        self.assertTrue(bkpt.IsValid(), "Bkpt is valid")504        write_bps = lldb.SBBreakpointList(self.orig_target)505 506        error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps)507        self.assertSuccess(error, "Failed writing breakpoints")508 509        orig_extra_args = side_effect.g_extra_args510        self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid")511 512        orig_keys = lldb.SBStringList()513        orig_extra_args.GetKeys(orig_keys)514        self.assertEqual(2, orig_keys.GetSize(), "Should have two keys")515 516        side_effect.g_extra_args = None517 518        copy_bps = lldb.SBBreakpointList(self.copy_target)519        error = self.copy_target.BreakpointsCreateFromFile(520            self.bkpts_file_spec, copy_bps521        )522        self.assertSuccess(error, "Failed reading breakpoints")523 524        self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.")525 526        copy_extra_args = side_effect.g_extra_args527        copy_keys = lldb.SBStringList()528        copy_extra_args.GetKeys(copy_keys)529        self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys")530 531        for idx in range(0, orig_keys.GetSize()):532            key = orig_keys.GetStringAtIndex(idx)533            copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100)534 535            if key == "first_arg":536                self.assertEqual(copy_value, "first_value")537            elif key == "second_arg":538                self.assertEqual(copy_value, "second_value")539            else:540                self.Fail("Unknown key: %s" % (key))541