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 NO_DEBUG_INFO_TESTCASE = True 18 19 def setUp(self): 20 # Call super's setUp(). 21 TestBase.setUp(self) 22 # Make the hidden directory in the build hierarchy: 23 lldbutil.mkdir_p(self.getBuildArtifact("hidden")) 24 25 # Invoke the default build rule. 26 self.build() 27 28 ext = 'so' 29 if self.platformIsDarwin(): 30 ext = 'dylib' 31 self.lib_name = 'libloadunload.' + ext 32 33 self.wd = os.path.realpath(self.getBuildDir()) 34 self.hidden_dir = os.path.join(self.wd, 'hidden') 35 self.hidden_lib = os.path.join(self.hidden_dir, self.lib_name) 36 37 @skipIfRemote 38 @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently 39 @expectedFlakeyNetBSD 40 @expectedFailureAll(oslist=["linux"], archs=['arm'], bugnumber="llvm.org/pr45894") 41 def test_load_using_paths(self): 42 """Test that we can load a module by providing a set of search paths.""" 43 if self.platformIsDarwin(): 44 dylibName = 'libloadunload_d.dylib' 45 else: 46 dylibName = 'libloadunload_d.so' 47 48 # The directory with the dynamic library we did not link to. 49 path_dir = os.path.join(self.getBuildDir(), "hidden") 50 51 (target, process, thread, 52 _) = lldbutil.run_to_source_breakpoint(self, 53 "Break here to do the load using paths", 54 lldb.SBFileSpec("main.cpp")) 55 error = lldb.SBError() 56 lib_spec = lldb.SBFileSpec(self.lib_name) 57 paths = lldb.SBStringList() 58 paths.AppendString(self.wd) 59 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 60 61 out_spec = lldb.SBFileSpec() 62 63 # First try with no correct directories on the path, and make sure that doesn't blow up: 64 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 65 self.assertEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Only looked on the provided path.") 66 # Make sure we got some error back in this case. Since we don't actually know what 67 # the error will look like, let's look for the absence of "unknown reasons". 68 error_str = error.description 69 self.assertNotEqual(len(error_str), 0, "Got an empty error string") 70 self.assertNotIn("unknown reasons", error_str, "Error string had unknown reasons") 71 72 # Now add the correct dir to the paths list and try again: 73 paths.AppendString(self.hidden_dir) 74 token = process.LoadImageUsingPaths(lib_spec, paths, out_spec, error) 75 76 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token") 77 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library") 78 79 # Make sure this really is in the image list: 80 loaded_module = target.FindModule(out_spec) 81 82 self.assertTrue(loaded_module.IsValid(), "The loaded module is in the image list.") 83 84 # Now see that we can call a function in the loaded module. 85 value = thread.frames[0].EvaluateExpression("d_function()", lldb.SBExpressionOptions()) 86 self.assertSuccess(value.GetError(), "Got a value from the expression") 87 ret_val = value.GetValueAsSigned() 88 self.assertEqual(ret_val, 12345, "Got the right value") 89 90 # Make sure the token works to unload it: 91 process.UnloadImage(token) 92 93 # Make sure this really is no longer in the image list: 94 loaded_module = target.FindModule(out_spec) 95 96 self.assertFalse(loaded_module.IsValid(), "The unloaded module is no longer in the image list.") 97 98 # Make sure a relative path also works: 99 paths.Clear() 100 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 101 paths.AppendString(self.wd) 102 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 103 104 out_spec = lldb.SBFileSpec() 105 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 106 107 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with relative path") 108 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with relative path") 109 110 process.UnloadImage(token) 111 112 # Make sure the presence of an empty path doesn't mess anything up: 113 paths.Clear() 114 paths.AppendString("") 115 paths.AppendString(os.path.join(self.wd, "no_such_dir")) 116 paths.AppendString(self.wd) 117 relative_spec = lldb.SBFileSpec(os.path.join("hidden", self.lib_name)) 118 119 out_spec = lldb.SBFileSpec() 120 token = process.LoadImageUsingPaths(relative_spec, paths, out_spec, error) 121 122 self.assertNotEqual(token, lldb.LLDB_INVALID_IMAGE_TOKEN, "Got a valid token with included empty path") 123 self.assertEqual(out_spec, lldb.SBFileSpec(self.hidden_lib), "Found the expected library with included empty path") 124 125 process.UnloadImage(token) 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