1""" 2Test that SBProcess.LoadImageUsingPaths works correctly. 3""" 4 5 6 7import os 8import lldb 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12 13 14@skipIfWindows # The Windows platform doesn't implement DoLoadImage. 15class LoadUsingPathsTestCase(TestBase): 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 NO_DEBUG_INFO_TESTCASE = True 20 21 def setUp(self): 22 # Call super's setUp(). 23 TestBase.setUp(self) 24 # Make the hidden directory in the build hierarchy: 25 lldbutil.mkdir_p(self.getBuildArtifact("hidden")) 26 27 # Invoke the default build rule. 28 self.build() 29 30 ext = 'so' 31 if self.platformIsDarwin(): 32 ext = 'dylib' 33 self.lib_name = 'libloadunload.' + ext 34 35 self.wd = os.path.realpath(self.getBuildDir()) 36 self.hidden_dir = os.path.join(self.wd, 'hidden') 37 self.hidden_lib = os.path.join(self.hidden_dir, self.lib_name) 38 39 @skipIfRemote 40 @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently 41 @expectedFlakeyNetBSD 42 @expectedFailureAll(oslist=["linux"], archs=['arm'], bugnumber="llvm.org/pr45894") 43 @skipIfReproducer # FIXME: Unexpected packet during (passive) replay 44 def test_load_using_paths(self): 45 """Test that we can load a module by providing a set of search paths.""" 46 if self.platformIsDarwin(): 47 dylibName = 'libloadunload_d.dylib' 48 else: 49 dylibName = 'libloadunload_d.so' 50 51 # The directory with the dynamic library we did not link to. 52 path_dir = os.path.join(self.getBuildDir(), "hidden") 53 54 (target, process, thread, 55 _) = lldbutil.run_to_source_breakpoint(self, 56 "Break here to do the load using paths", 57 lldb.SBFileSpec("main.cpp")) 58 error = lldb.SBError() 59 lib_spec = lldb.SBFileSpec(self.lib_name) 60 paths = lldb.SBStringList() 61 paths.AppendString(self.wd) 62 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 63 64 out_spec = lldb.SBFileSpec() 65 66 # First try with no correct directories on the path, and make sure that doesn't blow up: 67 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 68 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 69 70 # Now add the correct dir to the paths list and try again: 71 paths.AppendString(self.hidden_dir) 72 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 73 74 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 75 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 76 77 # Make sure this really is in the image list: 78 loaded_module = target.FindModule(out_spec) 79 80 self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.") 81 82 # Now see that we can call a function in the loaded module. 83 value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions()) 84 self.assertTrue(value.GetError().Success(), "Got a value from the expression") 85 ret_val = value.GetValueAsSigned() 86 self.assertEqual(ret_val, 12345, "Got the right value") 87 88 # Make sure the token works to unload it: 89 process.UnloadImage(token) 90 91 # Make sure this really is no longer in the image list: 92 loaded_module = target.FindModule(out_spec) 93 94 self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.") 95 96 # Make sure a relative path also works: 97 paths.Clear() 98 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 99 paths.AppendString(self.wd) 100 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 101 102 out_spec = lldb.SBFileSpec() 103 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 104 105 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with relative path") 106 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with relative path") 107 108 process.UnloadImage(token) 109 110 # Make sure the presence of an empty path doesn't mess anything up: 111 paths.Clear() 112 paths.AppendString("") 113 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 114 paths.AppendString(self.wd) 115 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 116 117 out_spec = lldb.SBFileSpec() 118 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 119 120 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with included empty path") 121 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with included empty path") 122 123 process.UnloadImage(token) 124 125 126 127 # Finally, passing in an absolute path should work like the basename: 128 # This should NOT work because we've taken hidden_dir off the paths: 129 abs_spec = lldb.SBFileSpec(os.path.join(self.hidden_dir, self.lib_name)) 130 131 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 132 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 133 134 # But it should work when we add the dir: 135 # Now add the correct dir to the paths list and try again: 136 paths.AppendString(self.hidden_dir) 137 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 138 139 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 140 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 141 142 143