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