1"""Test that types defined in shared libraries work correctly.""" 2 3 4import lldb 5from lldbsuite.test.decorators import * 6from lldbsuite.test.lldbtest import * 7import lldbsuite.test.lldbutil as lldbutil 8 9 10class SharedLibTestCase(TestBase): 11 def setUp(self): 12 # Call super's setUp(). 13 TestBase.setUp(self) 14 # Find the line number to break inside main(). 15 self.source = "shared.c" 16 self.line = line_number(self.source, "// Set breakpoint 0 here.") 17 self.shlib_names = ["foo"] 18 19 def common_setup(self): 20 # Run in synchronous mode 21 self.dbg.SetAsync(False) 22 self.runCmd("settings set symbols.load-on-demand true") 23 24 # Create a target by the debugger. 25 self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 26 self.assertTrue(self.target, VALID_TARGET) 27 28 # Register our shared libraries for remote targets so they get 29 # automatically uploaded 30 self.environment = self.registerSharedLibrariesWithTarget( 31 self.target, self.shlib_names 32 ) 33 34 ctx = self.platformContext 35 self.shared_lib_name = ctx.shlib_prefix + "foo." + ctx.shlib_extension 36 37 @skipIfWindows 38 def test_source_line_breakpoint(self): 39 self.build() 40 self.common_setup() 41 42 lldbutil.run_break_set_by_file_and_line( 43 self, "foo.c", 4, num_expected_locations=1, loc_exact=True 44 ) 45 46 # Now launch the process, and do not stop at entry point. 47 process = self.target.LaunchSimple( 48 None, self.environment, self.get_process_working_directory() 49 ) 50 self.assertTrue(process, PROCESS_IS_VALID) 51 52 # The stop reason of the thread should be breakpoint. 53 self.expect( 54 "thread list", 55 STOPPED_DUE_TO_BREAKPOINT, 56 substrs=["stopped", "stop reason = breakpoint"], 57 ) 58 # The breakpoint should have a hit count of 1. 59 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1) 60 61 thread = process.GetSelectedThread() 62 stack_frames = thread.frames 63 self.assertGreater(len(stack_frames), 2) 64 65 leaf_frame = stack_frames[0] 66 self.assertEqual("foo.c", leaf_frame.GetLineEntry().GetFileSpec().GetFilename()) 67 self.assertEqual(4, leaf_frame.GetLineEntry().GetLine()) 68 69 parent_frame = stack_frames[1] 70 self.assertEqual( 71 "shared.c", parent_frame.GetLineEntry().GetFileSpec().GetFilename() 72 ) 73 self.assertEqual(7, parent_frame.GetLineEntry().GetLine()) 74 75 @skipIfWindows 76 def test_symbolic_breakpoint(self): 77 self.build() 78 self.common_setup() 79 80 lldbutil.run_break_set_by_symbol( 81 self, "foo", sym_exact=True, num_expected_locations=1 82 ) 83 84 # Now launch the process, and do not stop at entry point. 85 process = self.target.LaunchSimple( 86 None, self.environment, self.get_process_working_directory() 87 ) 88 self.assertTrue(process, PROCESS_IS_VALID) 89 90 # The stop reason of the thread should be breakpoint. 91 self.expect( 92 "thread list", 93 STOPPED_DUE_TO_BREAKPOINT, 94 substrs=["stopped", "stop reason = breakpoint"], 95 ) 96 # The breakpoint should have a hit count of 1. 97 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1) 98 99 thread = process.GetSelectedThread() 100 stack_frames = thread.frames 101 self.assertGreater(len(stack_frames), 2) 102 103 leaf_frame = stack_frames[0] 104 self.assertEqual("foo.c", leaf_frame.GetLineEntry().GetFileSpec().GetFilename()) 105 self.assertEqual(4, leaf_frame.GetLineEntry().GetLine()) 106 107 parent_frame = stack_frames[1] 108 self.assertEqual( 109 "shared.c", parent_frame.GetLineEntry().GetFileSpec().GetFilename() 110 ) 111 self.assertEqual(7, parent_frame.GetLineEntry().GetLine()) 112 113 @skipIfWindows 114 def test_global_variable_hydration(self): 115 self.build() 116 self.common_setup() 117 118 lldbutil.run_break_set_by_file_and_line( 119 self, self.source, self.line, num_expected_locations=1, loc_exact=True 120 ) 121 122 # Now launch the process, and do not stop at entry point. 123 process = self.target.LaunchSimple( 124 None, self.environment, self.get_process_working_directory() 125 ) 126 self.assertTrue(process, PROCESS_IS_VALID) 127 128 # The stop reason of the thread should be breakpoint. 129 self.expect( 130 "thread list", 131 STOPPED_DUE_TO_BREAKPOINT, 132 substrs=["stopped", "stop reason = breakpoint"], 133 ) 134 135 # The breakpoint should have a hit count of 1. 136 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1) 137 138 self.expect( 139 "target variable --shlib a.out", 140 "Breakpoint in a.out should have hydrated the debug info", 141 substrs=["global_shared = 897"], 142 ) 143 144 self.expect( 145 "target variable --shlib " + self.shared_lib_name, 146 "shared library should not have debug info by default", 147 matching=False, 148 substrs=["global_foo"], 149 ) 150 151 self.expect( 152 "target variable global_foo --shlib " + self.shared_lib_name, 153 "Match global_foo in symbol table should hydrate debug info", 154 matching=True, 155 substrs=["global_foo = 321"], 156 ) 157