TestLoadUnload.py revision abb3302051246273eb92cca203c9a1b9d9736e05
1""" 2Test that breakpoint by symbol name works correctly with dynamic libs. 3""" 4 5import os, time 6import re 7import unittest2 8import lldb 9from lldbtest import * 10 11class LoadUnloadTestCase(TestBase): 12 13 mydir = os.path.join("functionalities", "load_unload") 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line number to break for main.cpp. 19 self.line = line_number('main.c', 20 '// Set break point at this line for test_lldb_process_load_and_unload_commands().') 21 self.line_d_function = line_number('d.c', 22 '// Find this line number within d_dunction().') 23 24 @unittest2.expectedFailure 25 def test_modules_search_paths(self): 26 """Test target modules list after loading a different copy of the library libd.dylib, and verifies that it works with 'target modules search-paths add'.""" 27 28 # Invoke the default build rule. 29 self.buildDefault() 30 31 if sys.platform.startswith("darwin"): 32 dylibName = 'libd.dylib' 33 34 # The directory with the the dynamic library we did not link to. 35 new_dir = os.path.join(os.getcwd(), "hidden") 36 37 old_dylib = os.path.join(os.getcwd(), dylibName) 38 new_dylib = os.path.join(new_dir, dylibName) 39 40 exe = os.path.join(os.getcwd(), "a.out") 41 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 42 43 self.expect("target modules list", 44 substrs = [old_dylib]) 45 self.expect("target modules list -t 3", 46 patterns = ["%s-[^-]*-[^-]*" % self.getArchitecture()]) 47 self.runCmd("target modules search-paths add %s %s" % (os.getcwd(), new_dir)) 48 49 self.expect("target modules search-paths list", 50 substrs = [os.getcwd(), new_dir]) 51 52 # Add teardown hook to clear image-search-paths after the test. 53 self.addTearDownHook(lambda: self.runCmd("target modules search-paths clear")) 54 self.expect("target modules list", "LLDB successfully locates the relocated dynamic library", 55 substrs = [new_dylib]) 56 57 58 def test_dyld_library_path(self): 59 """Test DYLD_LIBRARY_PATH after moving libd.dylib, which defines d_function, somewhere else.""" 60 61 # Invoke the default build rule. 62 self.buildDefault() 63 64 exe = os.path.join(os.getcwd(), "a.out") 65 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 66 67 if sys.platform.startswith("darwin"): 68 dylibName = 'libd.dylib' 69 dsymName = 'libd.dylib.dSYM' 70 dylibPath = 'DYLD_LIBRARY_PATH' 71 72 # The directory to relocate the dynamic library and its debugging info. 73 new_dir = os.path.join(os.getcwd(), "hidden") 74 75 old_dylib = os.path.join(os.getcwd(), dylibName) 76 new_dylib = os.path.join(new_dir, dylibName) 77 old_dSYM = os.path.join(os.getcwd(), dsymName) 78 new_dSYM = os.path.join(new_dir, dsymName) 79 80 #system(["ls", "-lR", "."]) 81 82 # Try running with the DYLD_LIBRARY_PATH environment variable set, make sure 83 # we pick up the hidden dylib. 84 85 env_cmd_string = "settings set target.env-vars " + dylibPath + "=" + new_dir 86 if self.TraceOn(): 87 print "Set environment to: ", env_cmd_string 88 self.runCmd(env_cmd_string) 89 self.runCmd("settings show target.env-vars") 90 91 remove_dyld_path_cmd = "settings remove target.env-vars " + dylibPath 92 self.addTearDownHook(lambda: self.runCmd(remove_dyld_path_cmd)) 93 94 self.expect("breakpoint set -f d.c -l %d" % self.line_d_function, 95 BREAKPOINT_CREATED, 96 startstr = "Breakpoint created: 1: file ='d.c', line = %d" % 97 self.line_d_function) 98 # For now we don't track DYLD_LIBRARY_PATH, so the old library will be in 99 # the modules list. 100 self.expect("target modules list", 101 substrs = [old_dylib], 102 matching=True) 103 104 self.runCmd("run") 105 self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, 106 patterns = ["frame #0.*d_function.*at d.c:%d" % self.line_d_function]) 107 108 # After run, make sure the hidden library is present, and the one we didn't 109 # load is not. 110 self.expect("target modules list", 111 substrs = [new_dylib]) 112 self.expect("target modules list", 113 substrs = [old_dylib], 114 matching=False) 115 116 def test_lldb_process_load_and_unload_commands(self): 117 """Test that lldb process load/unload command work correctly.""" 118 119 # Invoke the default build rule. 120 self.buildDefault() 121 122 exe = os.path.join(os.getcwd(), "a.out") 123 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 124 125 # Break at main.c before the call to dlopen(). 126 # Use lldb's process load command to load the dylib, instead. 127 128 self.expect("breakpoint set -f main.c -l %d" % self.line, 129 BREAKPOINT_CREATED, 130 startstr = "Breakpoint created: 1: file ='main.c', line = %d" % 131 self.line) 132 133 self.runCmd("run", RUN_SUCCEEDED) 134 135 # Make sure that a_function does not exist at this point. 136 self.expect("image lookup -n a_function", "a_function should not exist yet", 137 error=True, matching=False, 138 patterns = ["1 match found .* %s" % self.mydir]) 139 140 # Use lldb 'process load' to load the dylib. 141 self.expect("process load liba.dylib", "liba.dylib loaded correctly", 142 patterns = ['Loading "liba.dylib".*ok', 143 'Image [0-9]+ loaded']) 144 145 # Search for and match the "Image ([0-9]+) loaded" pattern. 146 output = self.res.GetOutput() 147 pattern = re.compile("Image ([0-9]+) loaded") 148 for l in output.split(os.linesep): 149 #print "l:", l 150 match = pattern.search(l) 151 if match: 152 break 153 index = match.group(1) 154 155 # Now we should have an entry for a_function. 156 self.expect("image lookup -n a_function", "a_function should now exist", 157 patterns = ["1 match found .*%s" % self.mydir]) 158 159 # Use lldb 'process unload' to unload the dylib. 160 self.expect("process unload %s" % index, "liba.dylib unloaded correctly", 161 patterns = ["Unloading .* with index %s.*ok" % index]) 162 163 self.runCmd("process continue") 164 165 def test_load_unload(self): 166 """Test breakpoint by name works correctly with dlopen'ing.""" 167 168 # Invoke the default build rule. 169 self.buildDefault() 170 171 exe = os.path.join(os.getcwd(), "a.out") 172 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 173 174 # Break by function name a_function (not yet loaded). 175 self.expect("breakpoint set -n a_function", BREAKPOINT_CREATED, 176 startstr = "Breakpoint created: 1: name = 'a_function', locations = 0 (pending)") 177 178 self.runCmd("run", RUN_SUCCEEDED) 179 180 # The stop reason of the thread should be breakpoint and at a_function. 181 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 182 substrs = ['stopped', 183 'a_function', 184 'stop reason = breakpoint']) 185 186 # The breakpoint should have a hit count of 1. 187 self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, 188 substrs = [' resolved, hit count = 1']) 189 190 # Issue the 'contnue' command. We should stop agaian at a_function. 191 # The stop reason of the thread should be breakpoint and at a_function. 192 self.runCmd("continue") 193 194 # rdar://problem/8508987 195 # The a_function breakpoint should be encountered twice. 196 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 197 substrs = ['stopped', 198 'a_function', 199 'stop reason = breakpoint']) 200 201 # The breakpoint should have a hit count of 2. 202 self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, 203 substrs = [' resolved, hit count = 2']) 204 205 206if __name__ == '__main__': 207 import atexit 208 lldb.SBDebugger.Initialize() 209 atexit.register(lambda: lldb.SBDebugger.Terminate()) 210 unittest2.main() 211