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