brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.6 KiB · 47af690 Raw
154 lines · python
1"""2Test how many times newly loaded binaries are notified;3they should be delivered in batches instead of one-by-one.4"""5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12@skipUnlessPlatform(["linux"] + lldbplatformutil.getDarwinOSTriples())13class ModuleLoadedNotifysTestCase(TestBase):14    NO_DEBUG_INFO_TESTCASE = True15 16    # At least DynamicLoaderDarwin and DynamicLoaderPOSIXDYLD should batch up17    # notifications about newly added/removed libraries.  Other DynamicLoaders may18    # not be written this way.19    def setUp(self):20        # Call super's setUp().21        TestBase.setUp(self)22        # Find the line number to break inside main().23        self.line = line_number("main.cpp", "// breakpoint")24 25    def setup_test(self, solibs):26        if lldb.remote_platform:27            path = lldb.remote_platform.GetWorkingDirectory()28            for f in solibs:29                lldbutil.install_to_target(self, self.getBuildArtifact(f))30        else:31            path = self.getBuildDir()32            if self.dylibPath in os.environ:33                sep = self.platformContext.shlib_path_separator34                path = os.environ[self.dylibPath] + sep + path35        self.runCmd(36            "settings append target.env-vars '{}={}'".format(self.dylibPath, path)37        )38        self.default_path = path39 40    def test_launch_notifications(self):41        """Test that lldb broadcasts newly loaded libraries in batches."""42 43        expected_solibs = [44            "lib_a." + self.platformContext.shlib_extension,45            "lib_b." + self.platformContext.shlib_extension,46            "lib_c." + self.platformContext.shlib_extension,47            "lib_d." + self.platformContext.shlib_extension,48        ]49 50        self.build()51        self.setup_test(expected_solibs)52 53        exe = self.getBuildArtifact("a.out")54        self.dbg.SetAsync(False)55 56        listener = self.dbg.GetListener()57        listener.StartListeningForEventClass(58            self.dbg,59            lldb.SBTarget.GetBroadcasterClassName(),60            lldb.SBTarget.eBroadcastBitModulesLoaded61            | lldb.SBTarget.eBroadcastBitModulesUnloaded,62        )63 64        # Create a target by the debugger.65        target = self.dbg.CreateTarget(exe)66        self.assertTrue(target, VALID_TARGET)67 68        # break on main69        breakpoint = target.BreakpointCreateByName("main", "a.out")70 71        event = lldb.SBEvent()72        # CreateTarget() generated modules-loaded events; consume them & toss73        while listener.GetNextEvent(event):74            True75 76        error = lldb.SBError()77        flags = target.GetLaunchInfo().GetLaunchFlags()78        process = target.Launch(79            listener,80            None,  # argv81            None,  # envp82            None,  # stdin_path83            None,  # stdout_path84            None,  # stderr_path85            None,  # working directory86            flags,  # launch flags87            False,  # Stop at entry88            error,89        )  # error90 91        self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)92 93        total_solibs_added = 094        total_solibs_removed = 095        total_modules_added_events = 096        total_modules_removed_events = 097        already_loaded_modules = []98        max_solibs_per_event = 099        max_solib_chunk_per_event = []100        while listener.GetNextEvent(event):101            if lldb.SBTarget.EventIsTargetEvent(event):102                if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded:103                    solib_count = lldb.SBTarget.GetNumModulesFromEvent(event)104                    total_modules_added_events += 1105                    total_solibs_added += solib_count106                    added_files = []107                    for i in range(solib_count):108                        module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event)109                        # On macOS Ventura and later, dyld and the main binary110                        # will be loaded again when dyld moves itself into the111                        # shared cache. Use the basename so this also works112                        # when reading dyld from the expanded shared cache.113                        exe_basename = lldb.SBFileSpec(exe).basename114                        if module.file.basename not in ["dyld", exe_basename]:115                            self.assertNotIn(116                                module,117                                already_loaded_modules,118                                "{} is already loaded".format(module),119                            )120                        already_loaded_modules.append(module)121                        added_files.append(module.GetFileSpec().GetFilename())122                    if self.TraceOn():123                        # print all of the binaries that have been added124                        print("Loaded files: %s" % (", ".join(added_files)))125 126                    # We will check the latest biggest chunk of loaded solibs.127                    # We expect all of our solibs in the last chunk of loaded modules.128                    if solib_count >= max_solibs_per_event:129                        max_solib_chunk_per_event = added_files.copy()130                        max_solibs_per_event = solib_count131 132                if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded:133                    solib_count = lldb.SBTarget.GetNumModulesFromEvent(event)134                    total_modules_removed_events += 1135                    total_solibs_removed += solib_count136                    if self.TraceOn():137                        # print all of the binaries that have been removed138                        removed_files = []139                        i = 0140                        while i < solib_count:141                            module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event)142                            removed_files.append(module.GetFileSpec().GetFilename())143                            i = i + 1144                        print("Unloaded files: %s" % (", ".join(removed_files)))145 146        # This is testing that we get back a small number of events with the loaded147        # binaries in batches.  Check that we got back more than 1 solib per event.148        # In practice on Darwin today, we get back two events for a do-nothing c149        # program: a.out and dyld, and then all the rest of the system libraries.150        # On Linux we get events for ld.so, [vdso], the binary and then all libraries,151        # but the different configurations could load a different number of .so modules152        # per event.153        self.assertLessEqual(set(expected_solibs), set(max_solib_chunk_per_event))154