import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @skipIfRemote def test_load_after_attach(self): self.build() sync_file_path = lldbutil.append_to_process_working_directory(self, "process_ready") ctx = self.platformContext lib_name = ctx.shlib_prefix + 'lib_b.' + ctx.shlib_extension exe = self.getBuildArtifact("a.out") lib = self.getBuildArtifact(lib_name) target = self.dbg.CreateTarget(exe) environment = self.registerSharedLibrariesWithTarget(target, ["lib_b"]) # Spawn a new process. # use realpath to workaround llvm.org/pr48376 # Pass path to solib for dlopen to properly locate the library. popen = self.spawnSubprocess(os.path.realpath(exe), [sync_file_path], extra_env=environment) lldbutil.wait_for_file_on_target(self, sync_file_path) # Attach to the spawned process. error = lldb.SBError() process = target.AttachToProcessWithID(self.dbg.GetListener(), popen.pid, error) self.assertSuccess(error) # Continue until first breakpoint. breakpoint1 = self.target().BreakpointCreateBySourceRegex( "// break here", lldb.SBFileSpec("main.cpp")) self.assertEqual(breakpoint1.GetNumResolvedLocations(), 1) stopped_threads = lldbutil.continue_to_breakpoint(self.process(), breakpoint1) self.assertEqual(len(stopped_threads), 1) # Change a variable to escape the loop self.runCmd("expression main_thread_continue = 1") # Continue so that dlopen is called. breakpoint2 = self.target().BreakpointCreateBySourceRegex( "// break after dlopen", lldb.SBFileSpec("main.cpp")) self.assertEqual(breakpoint2.GetNumResolvedLocations(), 1) stopped_threads = lldbutil.continue_to_breakpoint(self.process(), breakpoint2) self.assertEqual(len(stopped_threads), 1) # Check that image list contains liblib_b after dlopen. self.match( "image list", patterns = [lib_name], matching = True, msg = lib_name + " missing in image list")