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 def test_load_using_paths(self): 44 """Test that we can load a module by providing a set of search paths.""" 45 if self.platformIsDarwin(): 46 dylibName = 'libloadunload_d.dylib' 47 else: 48 dylibName = 'libloadunload_d.so' 49 50 # The directory with the dynamic library we did not link to. 51 path_dir = os.path.join(self.getBuildDir(), "hidden") 52 53 (target, process, thread, 54 _) = lldbutil.run_to_source_breakpoint(self, 55 "Break here to do the load using paths", 56 lldb.SBFileSpec("main.cpp")) 57 error = lldb.SBError() 58 lib_spec = lldb.SBFileSpec(self.lib_name) 59 paths = lldb.SBStringList() 60 paths.AppendString(self.wd) 61 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 62 63 out_spec = lldb.SBFileSpec() 64 65 # First try with no correct directories on the path, and make sure that doesn't blow up: 66 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 67 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 68 69 # Now add the correct dir to the paths list and try again: 70 paths.AppendString(self.hidden_dir) 71 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 72 73 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 74 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 75 76 # Make sure this really is in the image list: 77 loaded_module = target.FindModule(out_spec) 78 79 self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.") 80 81 # Now see that we can call a function in the loaded module. 82 value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions()) 83 self.assertTrue(value.GetError().Success(), "Got a value from the expression") 84 ret_val = value.GetValueAsSigned() 85 self.assertEqual(ret_val, 12345, "Got the right value") 86 87 # Make sure the token works to unload it: 88 process.UnloadImage(token) 89 90 # Make sure this really is no longer in the image list: 91 loaded_module = target.FindModule(out_spec) 92 93 self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.") 94 95 # Make sure a relative path also works: 96 paths.Clear() 97 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 98 paths.AppendString(self.wd) 99 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 100 101 out_spec = lldb.SBFileSpec() 102 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 103 104 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with relative path") 105 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with relative path") 106 107 process.UnloadImage(token) 108 109 # Make sure the presence of an empty path doesn't mess anything up: 110 paths.Clear() 111 paths.AppendString("") 112 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 113 paths.AppendString(self.wd) 114 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 115 116 out_spec = lldb.SBFileSpec() 117 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 118 119 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with included empty path") 120 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with included empty path") 121 122 process.UnloadImage(token) 123 124 125 126 # Finally, passing in an absolute path should work like the basename: 127 # This should NOT work because we've taken hidden_dir off the paths: 128 abs_spec = lldb.SBFileSpec(os.path.join(self.hidden_dir, self.lib_name)) 129 130 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 131 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 132 133 # But it should work when we add the dir: 134 # Now add the correct dir to the paths list and try again: 135 paths.AppendString(self.hidden_dir) 136 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 137 138 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 139 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 140 141 142