1import lldb 2from lldbsuite.test.decorators import * 3from lldbsuite.test.lldbtest import * 4from lldbsuite.test import lldbutil 5 6class TestCase(TestBase): 7 NO_DEBUG_INFO_TESTCASE = True 8 9 @skipIfRemote 10 def test_load_after_attach(self): 11 self.build() 12 13 ctx = self.platformContext 14 lib_name = ctx.shlib_prefix + 'lib_b.' + ctx.shlib_extension 15 16 exe = self.getBuildArtifact("a.out") 17 lib = self.getBuildArtifact(lib_name) 18 19 target = self.dbg.CreateTarget(exe) 20 environment = self.registerSharedLibrariesWithTarget(target, ["lib_b"]) 21 22 # Spawn a new process. 23 # use realpath to workaround llvm.org/pr48376 24 # Pass path to solib for dlopen to properly locate the library. 25 popen = self.spawnSubprocess(os.path.realpath(exe), extra_env=environment) 26 27 # Attach to the spawned process. 28 error = lldb.SBError() 29 process = target.AttachToProcessWithID(self.dbg.GetListener(), 30 popen.pid, error) 31 self.assertSuccess(error) 32 33 # Continue until first breakpoint. 34 breakpoint1 = self.target().BreakpointCreateBySourceRegex( 35 "// break here", lldb.SBFileSpec("main.cpp")) 36 self.assertEqual(breakpoint1.GetNumResolvedLocations(), 1) 37 stopped_threads = lldbutil.continue_to_breakpoint(self.process(), breakpoint1) 38 self.assertEqual(len(stopped_threads), 1) 39 40 # Change a variable to escape the loop 41 self.runCmd("expression main_thread_continue = 1") 42 43 # Continue so that dlopen is called. 44 breakpoint2 = self.target().BreakpointCreateBySourceRegex( 45 "// break after dlopen", lldb.SBFileSpec("main.cpp")) 46 self.assertEqual(breakpoint2.GetNumResolvedLocations(), 1) 47 stopped_threads = lldbutil.continue_to_breakpoint(self.process(), breakpoint2) 48 self.assertEqual(len(stopped_threads), 1) 49 50 # Check that image list contains liblib_b after dlopen. 51 self.match( 52 "image list", 53 patterns = [lib_name], 54 matching = True, 55 msg = lib_name + " missing in image list") 56 57