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 # Make sure we got some error back in this case. Since we don't actually know what 69 # the error will look like, let's look for the absence of "unknown reasons". 70 error_str = error.description 71 self.assertNotEqual(len(error_str), 0, "Got an empty error string") 72 self.assertNotIn("unknown reasons", error_str, "Error string had unknown reasons") 73 74 # Now add the correct dir to the paths list and try again: 75 paths.AppendString(self.hidden_dir) 76 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 77 78 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 79 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 80 81 # Make sure this really is in the image list: 82 loaded_module = target.FindModule(out_spec) 83 84 self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.") 85 86 # Now see that we can call a function in the loaded module. 87 value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions()) 88 self.assertSuccess(value.GetError(), "Got a value from the expression") 89 ret_val = value.GetValueAsSigned() 90 self.assertEqual(ret_val, 12345, "Got the right value") 91 92 # Make sure the token works to unload it: 93 process.UnloadImage(token) 94 95 # Make sure this really is no longer in the image list: 96 loaded_module = target.FindModule(out_spec) 97 98 self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.") 99 100 # Make sure a relative path also works: 101 paths.Clear() 102 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 103 paths.AppendString(self.wd) 104 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 105 106 out_spec = lldb.SBFileSpec() 107 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 108 109 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with relative path") 110 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with relative path") 111 112 process.UnloadImage(token) 113 114 # Make sure the presence of an empty path doesn't mess anything up: 115 paths.Clear() 116 paths.AppendString("") 117 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 118 paths.AppendString(self.wd) 119 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 120 121 out_spec = lldb.SBFileSpec() 122 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 123 124 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with included empty path") 125 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with included empty path") 126 127 process.UnloadImage(token) 128 129 # Finally, passing in an absolute path should work like the basename: 130 # This should NOT work because we've taken hidden_dir off the paths: 131 abs_spec = lldb.SBFileSpec(os.path.join(self.hidden_dir, self.lib_name)) 132 133 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 134 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 135 136 # But it should work when we add the dir: 137 # Now add the correct dir to the paths list and try again: 138 paths.AppendString(self.hidden_dir) 139 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 140 141 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 142 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 143