1"""Test that hidden ivars in a shared library are visible from the main executable.""" 2 3 4 5import unittest2 6import subprocess 7 8import lldb 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12 13 14class HiddenIvarsTestCase(TestBase): 15 16 mydir = TestBase.compute_mydir(__file__) 17 18 def setUp(self): 19 # Call super's setUp(). 20 TestBase.setUp(self) 21 # Find the line number to break inside main(). 22 self.source = 'main.m' 23 self.line = line_number(self.source, '// breakpoint1') 24 # The makefile names of the shared libraries as they appear in DYLIB_NAME. 25 # The names should have no loading "lib" or extension as they will be 26 # localized 27 self.shlib_names = ["InternalDefiner"] 28 29 @skipIf( 30 debug_info=no_match("dsym"), 31 bugnumber="This test requires a stripped binary and a dSYM") 32 @skipIfReproducer # FIXME: Unexpected packet during (passive) replay 33 def test_expr_stripped(self): 34 if self.getArchitecture() == 'i386': 35 self.skipTest("requires modern objc runtime") 36 else: 37 self.build() 38 self.expr(True) 39 40 @skipIfReproducer # FIXME: Unexpected packet during (passive) replay 41 def test_expr(self): 42 if self.getArchitecture() == 'i386': 43 self.skipTest("requires modern objc runtime") 44 else: 45 self.build() 46 self.expr(False) 47 48 @skipIf( 49 debug_info=no_match("dsym"), 50 bugnumber="This test requires a stripped binary and a dSYM") 51 def test_frame_variable_stripped(self): 52 if self.getArchitecture() == 'i386': 53 self.skipTest("requires modern objc runtime") 54 else: 55 self.build() 56 self.frame_var(True) 57 58 def test_frame_variable(self): 59 if self.getArchitecture() == 'i386': 60 self.skipTest("requires modern objc runtime") 61 else: 62 self.build() 63 self.frame_var(False) 64 65 @expectedFailure("rdar://18683637") 66 def test_frame_variable_across_modules(self): 67 if self.getArchitecture() == 'i386': 68 self.skipTest("requires modern objc runtime") 69 else: 70 self.build() 71 self.common_setup(False) 72 self.expect( 73 "frame variable k->bar", 74 VARIABLES_DISPLAYED_CORRECTLY, 75 substrs=["= 3"]) 76 77 def common_setup(self, strip): 78 79 if strip: 80 exe = self.getBuildArtifact("stripped/a.out") 81 else: 82 exe = self.getBuildArtifact("a.out") 83 # Create a target by the debugger. 84 target = self.dbg.CreateTarget(exe) 85 self.assertTrue(target, VALID_TARGET) 86 87 # Create the breakpoint inside function 'main'. 88 breakpoint = target.BreakpointCreateByLocation(self.source, self.line) 89 self.assertTrue(breakpoint, VALID_BREAKPOINT) 90 91 # Register our shared libraries for remote targets so they get 92 # automatically uploaded 93 environment = self.registerSharedLibrariesWithTarget( 94 target, self.shlib_names) 95 96 # Now launch the process, and do not stop at entry point. 97 process = target.LaunchSimple( 98 None, environment, self.get_process_working_directory()) 99 self.assertTrue(process, PROCESS_IS_VALID) 100 101 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 102 103 # Break inside the foo function which takes a bar_ptr argument. 104 lldbutil.run_break_set_by_file_and_line( 105 self, "main.m", self.line, num_expected_locations=1, loc_exact=True) 106 107 self.runCmd("run", RUN_SUCCEEDED) 108 109 # The stop reason of the thread should be breakpoint. 110 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 111 substrs=['stopped', 112 'stop reason = breakpoint']) 113 114 # The breakpoint should have a hit count of 1. 115 self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, 116 substrs=[' resolved, hit count = 1']) 117 118 def expr(self, strip): 119 self.common_setup(strip) 120 121 # This should display correctly. 122 self.expect( 123 "expression (j->_definer->foo)", 124 VARIABLES_DISPLAYED_CORRECTLY, 125 substrs=["= 4"]) 126 127 self.expect( 128 "expression (j->_definer->bar)", 129 VARIABLES_DISPLAYED_CORRECTLY, 130 substrs=["= 5"]) 131 132 if strip: 133 self.expect( 134 "expression *(j->_definer)", 135 VARIABLES_DISPLAYED_CORRECTLY, 136 substrs=["foo = 4"]) 137 else: 138 self.expect( 139 "expression *(j->_definer)", 140 VARIABLES_DISPLAYED_CORRECTLY, 141 substrs=[ 142 "foo = 4", 143 "bar = 5"]) 144 145 self.expect("expression (k->foo)", VARIABLES_DISPLAYED_CORRECTLY, 146 substrs=["= 2"]) 147 148 self.expect("expression (k->bar)", VARIABLES_DISPLAYED_CORRECTLY, 149 substrs=["= 3"]) 150 151 self.expect( 152 "expression k.filteredDataSource", 153 VARIABLES_DISPLAYED_CORRECTLY, 154 substrs=[ 155 ' = 0x', 156 '"2 elements"']) 157 158 if strip: 159 self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY, 160 substrs=["foo = 2", ' = 0x', '"2 elements"']) 161 else: 162 self.expect( 163 "expression *(k)", 164 VARIABLES_DISPLAYED_CORRECTLY, 165 substrs=[ 166 "foo = 2", 167 "bar = 3", 168 '_filteredDataSource = 0x', 169 '"2 elements"']) 170 171 def frame_var(self, strip): 172 self.common_setup(strip) 173 174 # This should display correctly. 175 self.expect( 176 "frame variable j->_definer->foo", 177 VARIABLES_DISPLAYED_CORRECTLY, 178 substrs=["= 4"]) 179 180 if not strip: 181 self.expect( 182 "frame variable j->_definer->bar", 183 VARIABLES_DISPLAYED_CORRECTLY, 184 substrs=["= 5"]) 185 186 if strip: 187 self.expect( 188 "frame variable *j->_definer", 189 VARIABLES_DISPLAYED_CORRECTLY, 190 substrs=["foo = 4"]) 191 else: 192 self.expect( 193 "frame variable *j->_definer", 194 VARIABLES_DISPLAYED_CORRECTLY, 195 substrs=[ 196 "foo = 4", 197 "bar = 5"]) 198 199 self.expect("frame variable k->foo", VARIABLES_DISPLAYED_CORRECTLY, 200 substrs=["= 2"]) 201 202 self.expect( 203 "frame variable k->_filteredDataSource", 204 VARIABLES_DISPLAYED_CORRECTLY, 205 substrs=[ 206 ' = 0x', 207 '"2 elements"']) 208 209 if strip: 210 self.expect( 211 "frame variable *k", 212 VARIABLES_DISPLAYED_CORRECTLY, 213 substrs=[ 214 "foo = 2", 215 '_filteredDataSource = 0x', 216 '"2 elements"']) 217 else: 218 self.expect( 219 "frame variable *k", 220 VARIABLES_DISPLAYED_CORRECTLY, 221 substrs=[ 222 "foo = 2", 223 "bar = 3", 224 '_filteredDataSource = 0x', 225 '"2 elements"']) 226