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